From 6be98476a0c6cc01e25ac39f3b9ec2f36929bd02 Mon Sep 17 00:00:00 2001
From: varshaa-1616 <varshaa.1616@gmail.com>
Date: Sat, 6 Dec 2025 01:41:42 +0530
Subject: [PATCH 01/10] Add QC + Full MNE Report tutorial

---
 doc/optipng-0.7.8-win64/OptiPNG.url         |   2 +
 doc/optipng-0.7.8-win64/doc/authors.txt     |  31 +
 doc/optipng-0.7.8-win64/doc/history.txt     | 435 ++++++++++
 doc/optipng-0.7.8-win64/doc/license.txt     |  21 +
 doc/optipng-0.7.8-win64/doc/optipng.man.pdf | Bin 0 -> 42393 bytes
 doc/optipng-0.7.8-win64/doc/optipng.man.txt | 299 +++++++
 doc/optipng-0.7.8-win64/doc/todo.txt        |  42 +
 doc/optipng-0.7.8-win64/optipng.exe         | Bin 0 -> 229888 bytes
 tutorials/intro/70_report.py                | 880 +++++---------------
 9 files changed, 1054 insertions(+), 656 deletions(-)
 create mode 100644 doc/optipng-0.7.8-win64/OptiPNG.url
 create mode 100644 doc/optipng-0.7.8-win64/doc/authors.txt
 create mode 100644 doc/optipng-0.7.8-win64/doc/history.txt
 create mode 100644 doc/optipng-0.7.8-win64/doc/license.txt
 create mode 100644 doc/optipng-0.7.8-win64/doc/optipng.man.pdf
 create mode 100644 doc/optipng-0.7.8-win64/doc/optipng.man.txt
 create mode 100644 doc/optipng-0.7.8-win64/doc/todo.txt
 create mode 100644 doc/optipng-0.7.8-win64/optipng.exe

diff --git a/doc/optipng-0.7.8-win64/OptiPNG.url b/doc/optipng-0.7.8-win64/OptiPNG.url
new file mode 100644
index 00000000000..9796437165b
--- /dev/null
+++ b/doc/optipng-0.7.8-win64/OptiPNG.url
@@ -0,0 +1,2 @@
+[InternetShortcut]
+URL=http://optipng.sourceforge.net/
diff --git a/doc/optipng-0.7.8-win64/doc/authors.txt b/doc/optipng-0.7.8-win64/doc/authors.txt
new file mode 100644
index 00000000000..0245e5ab1be
--- /dev/null
+++ b/doc/optipng-0.7.8-win64/doc/authors.txt
@@ -0,0 +1,31 @@
+# OptiPNG version 0.7.8
+# Copyright (C) 2001-2023 Cosmin Truta and the Contributing Authors.
+# See the accompanying LICENSE file for details.
+#
+# A Contributing Author is a person or company who contributed code that
+# is now part of OptiPNG.
+#
+# For the purpose of copyright and licensing, this is the official list
+# of Contributing Authors, in alphabetic order.
+
+Adam Ciarcinski
+Brian McQuade
+Elias Pipping
+Fabien Barbier
+Friedrich Preuss
+Maciej Pilichowski
+Matthew Fearnley
+Nelson A. de Oliveira
+Niels de Koning
+Oliver Schneider
+Petr Gajdos
+Piotr Bandurski
+Priit Laes
+Ramona C. Truta
+Sebastian Pipping
+Stefan Br�ns
+Thomas Hurst
+Till Maas
+Ville Skytt�
+Vincent Lef�vre
+Yuen Ho Wong
diff --git a/doc/optipng-0.7.8-win64/doc/history.txt b/doc/optipng-0.7.8-win64/doc/history.txt
new file mode 100644
index 00000000000..ccd3746dc2e
--- /dev/null
+++ b/doc/optipng-0.7.8-win64/doc/history.txt
@@ -0,0 +1,435 @@
+OptiPNG - Revision history
+==========================
+
+Legend
+------
+++ Added or improved performance-related feature
+   (might improve compression ratio or processing speed).
+ + Added or improved feature.
+ - Removed feature.
+ ! Fixed bug.
+!! Fixed critical bug
+   (crash, data/metadata loss or security hazard).
+ * Other modification (e.g. architectural improvement).
+
+Version 0.7.8   2023-nov-03
+-------------
+ * Upgraded libpng to version 1.6.40.
+ * Upgraded zlib to version 1.3-optipng.
+ * Upgraded cexcept to version 2.0.2-optipng.
+!! Fixed a global-buffer-overflow vulnerability in the GIF reader.
+   [Reported by Zeng Yunxiang; fixed by Thomas Hurst]
+ ! Fixed a stack-print-after-scope defect in the error handler.
+ ! Fixed an assertion failure in the image reduction module.
+ ! Fixed the command-line wildargs expansion in the Windows port.
+ * Raised the minimum required libpng version from 1.2.9 to 1.6.35.
+ * Raised the minimum required zlib version from 1.2.1 to 1.2.8.
+ * Refactored the structured exception handling.
+
+Version 0.7.7   2017-dec-27
+-------------
+ * Upgraded libpng to version 1.6.34.
+ * Upgraded zlib to version 1.2.11-optipng.
+ * Upgraded minitiff to version 0.2.
+!! Fixed a buffer overflow vulnerability in the GIF decoder.
+   [Reported by Joonun Jang]
+!! Fixed an integer overflow vulnerability in the TIFF decoder.
+   [Reported by Jaeseung Choi]
+ ! Fixed the build on macOS High Sierra.
+   [Reported by various users]
+   [Fixed by Yuen Ho Wong and Friedrich Preuss]
+ ! Fixed the build on DJGPP.
+ * Disallowed out-of-bounds values in rangeset options.
+
+Version 0.7.6   2016-apr-03   [Released by Ramona C. Truta]
+-------------
+ * Upgraded libpng to version 1.6.21.
+ ! Fixed an assertion failure in the image reduction code.
+   [Fixed by upgrading libpng]
+!! Fixed various security-sensitive defects in the BMP decoder.
+   [Reported by Henri Salo and Hans Jerry Illikainen]
+   [Fixed by Ramona C. Truta]
+ ! Fixed a benign uninitialized memory read in the GIF decoder.
+   [Reported by Gustavo Grieco]
+ ! Fixed a build failure occurring under the Estonian (et_EE) locale.
+   [Reported by Sebastian Pipping]
+   [Fixed by Priit Laes]
+ ! Fixed a build failure occurring on Mac OS X, FreeBSD, and possibly
+   other systems that lack POSIX-compliant high-resolution timestamps.
+   [Reported by Ryan Schmidt and Dmitry Egorov]
+   [Contributed by Sebastian Pipping]
+ ! Fixed a typo causing build failures in 32-bit ANSI C compilation.
+   [Reported by various users]
+
+Version 0.7.5   2014-mar-24
+-------------
+ * Upgraded libpng to version 1.6.10-optipng.
+ * Upgraded zlib to version 1.2.8-optipng.
+ ! Fixed various build issues with libpng-1.5 and libpng-1.6.
+   [Fixed by Oliver Schneider]
+ * Allowed the handling of huge image files (> millions of pixels
+   per row or column) to be independent of the libpng version.
+ + Allowed the option -preserve to save the file ownership (UID/GID)
+   on Unix.
+   [Requested by Otto Kek�l�inen]
+ ! Fixed a build issue with Clang.
+ + Added various enhancements to the configure script.
+
+Version 0.7.4   2012-oct-21
+-------------
+!! Fixed the previous fix, which failed to fix the option -fix.
+   [Reported by Gynvael Coldwind and Mateusz Jurczyk]
+
+Version 0.7.3   2012-sep-16
+-------------
+!! Fixed a use-after-free vulnerability in the palette reduction code.
+   This vulnerability was accidentally introduced in version 0.7.
+
+Version 0.7.2   2012-aug-24
+-------------
+ * Upgraded libpng to version 1.4.12.
+ * Upgraded zlib to version 1.2.7-optipng.
+ ! Fixed the display of huge (4GB+) file/IDAT sizes on 32-bit platforms.
+ ! Issued a proper error message if the output IDAT can't fit in 2GB.
+   Acknowledged this limitation in the user manual.
+   [Reported by John Sauter]
+ ! Fixed the output file cleanup that should occur after a write error.
+ * Added the option -debug and various undocumented debug features.
+ * Moved the PNG reduction module (opngreduc) to a separate sub-project.
+
+Version 0.7.1   2012-mar-19   [Released by Ramona C. Truta]
+-------------
+!! Fixed a regression in the reduction of palette-encoded grayscale
+   images. (This regression was introduced in version 0.7.)
+   [Fixed by Adam Ciarcinski]
+
+Version 0.7     2012-feb-29   [Released by Cosmin & Ramona C. Truta]
+-----------
+ * Upgraded libpng to version 1.4.9.
+ * Upgraded zlib to version 1.2.6-optipng.
+!! Fixed a rarely-occurring out-of-bounds memory access error in
+   the Z_RLE strategy in zlib.
+   [Reported by Christopher Wichura]
+   [Fixed by upgrading zlib]
+ + Added the popularly-requested option -strip.
+   The only suboption currently supported is "-strip all".
+ + Added the option -clobber.
+   [Contributed by Maciej Pilichowski]
+ + Added the option -backup, as an alias of -keep.
+   [Contributed by Ramona C. Truta]
+ + Added the option -silent, as an alias of -quiet.
+   [Contributed by Ramona C. Truta]
+ - Deprecated the option -log.
+   [Contributed by Ramona C. Truta]
+ * Changed the activity display output from STDOUT to STDERR.
+ + Allowed the option -preserve to save high-resolution timestamps
+   on Unix, if the POSIX-1.2008 API is available.
+   (This feature was previously available on Windows only.)
+ ! Fixed a minor precision error in the display of file size percents.
+ ! Fixed a memory leak that occurred when reading broken GIF images.
+ ! Fixed various build issues.
+   [Fixed by Sebastian Pipping and Ville Skytt�]
+ * Resolved all remaining compatibility issues with libpng-1.5.
+   [Contributed by Adam Ciarcinski]
+ * Added build support for clang.
+ * Reorganized the source directory structure.
+
+Version 0.6.5   2011-jan-24
+-------------
+ * Upgraded libpng to version 1.4.5-optipng.
+ * Upgraded zlib to version 1.2.5-optipng.
+!! Fixed the I/O states (in libpng 1.4.5);
+   they caused incorrect file reads in some rare cases.
+   [Reported by Dmitry Marakasov]
+!! Fixed processing of PNG files with chunks of size 0.
+   [Reported by Matthew Fearnley]
+ ! Fixed a display error in the TIFF import.
+   [Fixed by Piotr Bandurski]
+ + Improved checking of the arguments of -f, -zc, -zm and -zs.
+ - Removed quirks from the rangeset option argument syntax.
+ ! Fixed a build issue under the system-supplied libpng-1.4.
+   [Fixed by Petr Gajdos]
+ * Resolved forward-compatibility issues regarding libpng-1.5;
+   however, the system-supplied libpng-1.5 is not yet supported.
+ * Added various enhancements to the configure+make build system.
+   [Contributed by Elias Pipping and Dmitri Zubko]
+
+Version 0.6.4   2010-mar-14
+-------------
+ * Upgraded libpng to version 1.4.1-optipng.
+ * Upgraded zlib to version 1.2.4-optipng.
+ + Added the option -nx.
+ * Clarified the behavior of the option -nz and the relationship between
+   the options -nz and -o0.
+ + Added a filesystem check (resolving normalized paths, symlinks, etc.)
+   to better detect when the output overwrites the input.
+ + Enabled automatic wildcard expansion (i.e. globbing) on Win64.
+ ! Fixed a Unicode build issue on Windows.
+   [Fixed by Fabien Barbier]
+
+Version 0.6.3   2009-may-18
+-------------
+ * Upgraded libpng to version 1.2.36-optipng.
+!! Fixed a use-after-free error in the GIF reader.
+   [Reported by Roy Tam]
+   [Fixed by Bryan McQuade]
+ ! Flushed the output log to display the current trial in real time.
+   This only worked on Windows in the previous version.
+   [Fixed by Vincent Lef�vre]
+ ! Fixed an error in reporting unrecognized file formats.
+ - Removed the requirement to "fix" TIFF files that contain unrecognized
+   metadata.
+   [Requested by Piotr Bandurski]
+ * Simplified the option abbreviation rules. Option names can now be
+   abbreviated to their shortest unique prefix, as in X11 applications.
+
+Version 0.6.2   2008-nov-09
+-------------
+ * Upgraded libpng to version 1.2.33-optipng.
+++ Put back a speed optimization, accidentally removed in version 0.6,
+   allowing singleton trials (-o1) to be bypassed in certain conditions.
+!! Fixed an array overflow in the BMP reader.
+!! Fixed the loss of private chunks under the option -snip.
+ + Produced a more concise on-screen output in the non-verbose mode.
+   [Contributed by Vincent Lef�vre]
+ * Added a programming interface to the optimization engine, in order
+   to facilitate the development of PNG-optimizing GUI apps and plugins.
+
+Version 0.6.1   2008-jul-20
+-------------
+ * Upgraded cexcept to version 2.0.1.
+ + Added a configure script, to be used instead of unix-secure.mak.
+ ! Fixed a build issue that occurred when using libpng from the system.
+   [Reported by Nelson A. de Oliveira]
+ ! Fixed the processing when the image reduction yields an output larger
+   than the original.
+   [Reported by Michael Krishtopa]
+ ! Fixed the behavior of the option -preserve.
+   [Reported by Bill Koch]
+ - Removed displaying of partial progress when abandoning IDATs under
+   the option -v. (The percentages displayed were not very accurate.)
+
+Version 0.6     2008-jun-15
+-----------
+ * Upgraded libpng to version 1.2.29-optipng.
+++ Implemented grayscale(alpha)-to-palette reductions.
+++ Improved conversion of bKGD info during RGB-to-palette reductions.
+   [Contributed by Matthew Fearnley]
+!! Fixed conversion of bKGD and tRNS during 16-to-8-bit reductions.
+   [Reported by Matthew Fearnley]
+ + Added support for compressed BMP (incl. PNG-compressed BMP, you bet!)
+ + Improved the speed of reading raw PNM files.
+ + Recognized PNG digital signatures (dSIG) and disabled optimization
+   in their presence, to preserve their integrity.
+ + Allowed the user to enforce the optimization of dSIG'ed files.
+ + Recognized APNG animation files and disabled reductions to preserve
+   their integrity.
+ + Added the option -snip, to allow the user to snip one image out of
+   a multi-image file, such as animated GIF, multi-page TIFF, or APNG.
+ + Improved recovery of PNG files with incomplete IDAT.
+!! Fixed a crash triggered by the use of -log on some platforms.
+   [Fixed by Stefan Br�ns]
+ ! Fixed the behavior of the options -out and -dir when the input is
+   already optimized.
+   [Reported by Christian Davideck]
+ * Provided more detailed image information at the start of processing.
+ * Provided a more detailed summary at the end of processing, under the
+   presence of the option -v and/or the occurrence of exceptional events.
+
+Version 0.5.5   2007-jan-28
+-------------
+ * Upgraded libpng to version 1.2.15-optipng.
+++ Used a previously-missed RGB-to-palette reduction opportunity
+   for images containing 256 distinct colors.
+   [Reported by Joachim Kluge]
+!! Fixed conversion of bKGD info during RGB-to-palette reductions.
+   [Reported by Matthew Fearnley]
+ ! Fixed pre-computation of iterations.
+   [Reported by Matthew Fearnley]
+ ! Eliminated a false alarm when processing RGB images with tRNS
+   in Unix-secure mode.
+   [Reported by Till Maas]
+   [Fixed by Nelson A. de Oliveira]
+ ! Fixed the behavior of the options -out and -dir when changing
+   interlacing.
+   [Reported by Martin Packman]
+ ! Fixed the behavior of "-dir [DRIVE]:" on Windows.
+
+Version 0.5.4   2006-aug-11
+-------------
+ + Added the options -out and -dir, to specify the name of the
+   output file or directory.
+   [Requested by Alexander Lucas]
+ * Added support for builds based on the system-supplied libpng.
+   [Contributed by Nelson A. de Oliveira]
+
+Version 0.5.3   2006-jul-23
+-------------
+ * Upgraded libpng to version 1.2.12-optipng.
+ + Implemented basic support for TIFF (grayscale, RGB and RGBA,
+   uncompressed).
+++ Avoided the redundant trial when the search space is singular
+   (e.g. when running "optipng -o1 example.tif").
+ + Prevented accidental file corruption when using the option -log.
+ ! Fixed (again) a small typo in the online help.
+
+Version 0.5.2   2006-may-07
+-------------
+ + Improved handling of inexact PNM-to-PNG conversions.
+ ! Fixed a typo that was breaking the build on some Unix platforms.
+   [Reported by Aaron Reitz]
+
+Version 0.5.1   2006-apr-30
+-------------
+++ Implemented bit depth reduction for palette images.
+ * Upgraded libpng to version 1.2.10-optipng.
+ + Improved the BMP support.
+ + Added a Unix man page.
+   [Contributed by Nelson A. de Oliveira]
+ + Allowed abbreviation of command-line options.
+ + Changed the option -log to accept a file name as an argument.
+ * Renamed the option -no to -simulate.
+ ! Fixed an error in handling .bak files on Unix.
+   [Reported by Adam Szojda and Nelson A. de Oliveira]
+ ! Fixed a small typo in the help screen.
+   [Reported by A. Costa and Nelson A. de Oliveira]
+
+Version 0.5     2006-jan-14
+-----------
+++ Added pngxtern, a libpng add-on for external image format
+   support: BMP (uncompressed), GIF, PNM.
+++ Implemented RGB(A)-to-palette reductions.
+ * Upgraded zlib to version 1.2.3-optipng.
+ * Upgraded libpng to version 1.2.8-optipng.
+ + If trials are ended prematurely, detailed progression is only
+   reported under the option -v.
+ - Removed reporting of some IDAT sizes that exceeded the optimum.
+   (This was NOT a bug, but a "feature" that confused some users.)
+ ! Fixed an RGB-to-gray reduction problem that occurred under some
+   specific background colors.
+ * Added support for builds based on the system-supplied zlib.
+   [Requested by Nelson A. de Oliveira]
+ * Modified LICENSE. It is now a verbatim spell of the zlib license.
+
+Version 0.4.8   2005-may-10
+-------------
+ * Upgraded libpng to version 1.0.18-optipng.
+!! Fixed a palette-to-gray reduction problem that occurred when an
+   RGB triple had both an alpha below max, and an alpha equal to max.
+   [Reported by Nicolas Le Gland]
+ + Packed the Windows executable using UPX.
+
+Version 0.4.7   2004-oct-30
+-------------
+!! Fixed a palette-to-gray reduction problem that occurred when
+   having more than one alpha value per RGB triple.
+   [Reported by Larry Hastings]
+ ! Fixed the progress display, when processing very large images.
+ + Displayed the image info at the beginning of processing.
+++ Reduced the IDAT buffer size, allowing abandoned trials to
+   terminate earlier in some circumstances.
+ + Implemented error recovery, when PLTE is too small, and/or
+   tRNS is too large.
+
+Version 0.4.6   2004-oct-25
+-------------
+ * Upgraded zlib to version 1.2.2-optipng.
+ * Upgraded libpng to version 1.0.17-optipng.
+   This provides safe handling of some ill-formed PNG images.
+ + Rewrote makefiles.
+ + Added project workspace to build under Visual C++ 6.0,
+   integrated with memory leak detection.
+++ Implemented a premature termination of trials, in the moment
+   when IDAT grows beyond the smallest size previously achieved.
+   [Requested by Larry Hastings]
+ + Changed the order of trials, to perform the trials that are
+   more likely to yield a smaller IDAT, at the beginning.
+ + Added the option -full to avoid the premature termination of
+   trials; useful for debugging.
+
+Version 0.4.5   2004-may-31
+-------------
+ * Upgraded zlib to version 1.2.1.f-cos2.
+ * Upgraded libpng to version 1.0.15-cos2.
+ * Renamed the option -nx to -nz.
+ + Added the option -preserve to preserve file attributes
+   (file mode, time stamp, etc.) where applicable.
+   [Requested by Nehal Mistry]
+ ! Fixed an incorrect initialization of zlib window bits.
+ ! Displayed an error message when the search space was invalid.
+!! Fixed a palette reduction problem for bit depths below 8.
+ ! Eliminated memory leaks.
+   [Contributed by Niels de Koning]
+
+Version 0.4.4   2003-nov-20
+-------------
+ * Upgraded zlib to version 1.2.1.
+++ Added support for the Z_RLE strategy.
+
+Version 0.4.3   2003-aug-12
+-------------
+ ! Fixed a reduction problem that caused an assertion failure.
+   [Reported by Dimitri Papadopoulos]
+
+Version 0.4.2   2003-jun-30
+-------------
+++ Enhanced the support for palette size reductions:
+   trailing sterile palette entries are removed even when
+   the bit depth is below 8.
+ ! Enforced recompression when the new IDAT has the same size,
+   but other chunks have been reduced.
+ + Displayed the IDAT size difference as a percentage.
+   [Requested by Nehal Mistry]
+
+Version 0.4.1   2003-may-19
+-------------
+ ! Fixed the removal of trailing sterile palette entries.
+
+Version 0.4     2003-may-12
+-----------
+++ Added support for palette-to-gray reductions.
+++ Added partial support for palette size reductions.
+ ! Fixed the reporting of invalid command-line options.
+ ! Eliminated a spurious warning when the zlib window size
+   is set to 256.
+
+Version 0.3.2   2003-mar-11
+-------------
+ + Added support for updating sBIT during reductions.
+ ! Fixed the reduction of the alpha channel.
+
+Version 0.3.1   2003-feb-25
+-------------
+ ! Fixed the encoding of interlaced images when they become
+   larger than the input.
+   [Reported by James H. Cloos, Jr.]
+ + Added the HISTORY document (this file).
+
+Version 0.3     2003-feb-24
+-----------
+ * Announced the first public release of OptiPNG.
+++ Added support for iterating through zlib memory levels.
+++ Added support for collapsing IDAT, avoiding calls to
+   png_set_compression_buffer_size().
+   This reduces the memory requirements.
+++ Added support for lossless reduction of the image type:
+   RGB[A] -> G[A], RGBA -> RGB, GA -> G
+ + Added many user options.
+ + Added documentation.
+
+Version 0.2     2001-dec-27
+-----------
+ + Added support for optimization level presets.
+ + Added a user option for changing the interlacing.
+
+Version 0.1     2001-dec-17
+-----------
+ + Added support for chunk I/O status annotation.
+   This improves the speed of OptiPNG significantly.
+ * Added structured exception handling via cexcept.
+
+Version 0.0.1   2001-dec-10
+-------------
+ * Introduced OptiPNG.
+++ Compressed PNG IDAT data repeatedly, iterating through zlib
+   compression and strategy levels, as well as PNG delta filters.
diff --git a/doc/optipng-0.7.8-win64/doc/license.txt b/doc/optipng-0.7.8-win64/doc/license.txt
new file mode 100644
index 00000000000..58fbad30883
--- /dev/null
+++ b/doc/optipng-0.7.8-win64/doc/license.txt
@@ -0,0 +1,21 @@
+Copyright (C) 2001-2023 Cosmin Truta and the Contributing Authors.
+For the purpose of copyright and licensing, the list of Contributing
+Authors is available in the accompanying AUTHORS file.
+
+This software is provided 'as-is', without any express or implied
+warranty.  In no event will the author(s) be held liable for any damages
+arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not
+   claim that you wrote the original software.  If you use this software
+   in a product, an acknowledgment in the product documentation would be
+   appreciated but is not required.
+
+2. Altered source versions must be plainly marked as such, and must not
+   be misrepresented as being the original software.
+
+3. This notice may not be removed or altered from any source distribution.
diff --git a/doc/optipng-0.7.8-win64/doc/optipng.man.pdf b/doc/optipng-0.7.8-win64/doc/optipng.man.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..4f8b7083bf4c48e3a60fb7a118bbf5825f78889b
GIT binary patch
diff --git a/doc/optipng-0.7.8-win64/doc/optipng.man.txt b/doc/optipng-0.7.8-win64/doc/optipng.man.txt
new file mode 100644
index 00000000000..f2b1a458ea6
--- /dev/null
+++ b/doc/optipng-0.7.8-win64/doc/optipng.man.txt
@@ -0,0 +1,299 @@
+OPTIPNG(1)                  General Commands Manual                 OPTIPNG(1)
+
+NAME
+       OptiPNG - Optimize Portable Network Graphics files
+
+SYNOPSIS
+       optipng [-? | -h | -help]
+       optipng [options...] files...
+
+DESCRIPTION
+       The  OptiPNG  program  shall attempt to optimize PNG files, i.e. reduce
+       their size to a minimum, without losing semantic information. In  addi-
+       tion,  this  program  shall perform a suite of auxiliary functions like
+       integrity checks, metadata recovery and pixmap-to-PNG conversion.
+
+       The optimization attempts are not  guaranteed  to  succeed.  Valid  PNG
+       files  that  cannot  be optimized by this program are normally left in-
+       tact; their size will not grow. The user may request to  override  this
+       default behavior.
+
+FILES
+       The  input  files  are  raster image files encoded either in PNG format
+       (the native format), or in an external format. The currently  supported
+       external formats are GIF, BMP, PNM and TIFF.
+
+       OptiPNG processes each image file given in the command line as follows:
+
+       - If the image is in PNG format:
+
+              Attempts to optimize the given file in-place. If optimization is
+              successful,  or  if  the  option -force is enabled, replaces the
+              original file with its optimized version. The original  file  is
+              backed up if the option -keep is enabled.
+
+       - If the image is in an external format:
+
+              Creates  an  optimized PNG version of the given file. The output
+              file name is composed from the original file name and  the  .png
+              extension.
+
+       Existing  files  are not overwritten, unless the option -clobber is en-
+       abled.
+
+OPTIONS
+   General options
+       -?, -h, -help
+              Show a complete summary of options.
+
+       -backup, -keep
+              Keep a backup of the modified files.
+
+       -clobber
+              Overwrite the existing output and backup files.
+              Under this option, if the option -backup is not enabled, the old
+              backups of the overwritten files are deleted.
+
+       -dir directory
+              Write the output files to directory.
+
+       -fix   Enable error recovery. This option has no effect on valid  input
+              files.
+              The  program will spend a reasonable amount of effort to recover
+              as much data as possible, without  increasing  the  output  file
+              size,  but  the success cannot be generally guaranteed. The pro-
+              gram may even increase the file size,  e.g.,  by  reconstructing
+              missing  critical  data. Under this option, integrity shall take
+              precedence over file size.
+              When this option is not used, the invalid input files  are  left
+              unprocessed.
+
+       -force Enforce writing of a new output file.
+              This  option  overrides the program's decision not to write such
+              file, e.g. when the PNG input is digitally signed (using  dSIG),
+              or when the PNG output becomes larger than the PNG input.
+
+       -log file
+              Log  messages  to  file.  For safety reasons, file must have the
+              extension .log.
+              This option is deprecated and will be  removed  eventually.  Use
+              shell redirection.
+
+       -out file
+              Write  output  file  to file.  The command line must contain ex-
+              actly one input file.
+
+       -preserve
+              Preserve file attributes (time stamps, file access rights, etc.)
+              where applicable.
+
+       -quiet, -silent
+              Run in quiet mode.
+              The messages are still written to the log  file  if  the  option
+              -log is enabled.
+
+       -simulate
+              Run  in  simulation  mode: perform the trials, but do not create
+              output files.
+
+       -v     Enable the options -verbose and -version.
+
+       -verbose
+              Run in verbose mode.
+
+       -version
+              Show copyright, version and build info.
+
+       --     Stop option switch parsing.
+
+   PNG encoding and optimization options
+       -o level
+              Select the optimization level.
+              The optimization level 0 enables a set  of  optimization  opera-
+              tions  that  require minimal effort. There will be no changes to
+              image attributes like bit depth or color type, and no recompres-
+              sion of existing IDAT datastreams.
+              The optimization level  1  enables  a  single  IDAT  compression
+              trial. The trial chosen is what OptiPNG thinks it's probably the
+              most effective.
+              The  optimization  levels 2 and higher enable multiple IDAT com-
+              pression trials; the higher the level, the more trials.
+              The behavior and the default value of  this  option  may  change
+              across  different program versions. Use the option -h to see the
+              details pertaining to your specific version.
+
+       -f filters
+              Select the PNG delta filters.
+              The filters argument is specified as a  rangeset  (e.g.  -f0-5),
+              and  the default filters value depends on the optimization level
+              set by the option -o.
+              The filter values 0, 1, 2, 3 and 4  indicate  static  filtering,
+              and correspond to the standard PNG filter codes (None, Left, Up,
+              Average  and  Paeth, respectively). The filter value 5 indicates
+              adaptive filtering, whose effect is defined by the libpng(3) li-
+              brary used by OptiPNG.
+
+       -full  Produce a full report on IDAT.  This option might slow down  the
+              trials.
+
+       -i type
+              Select the interlace type (0-1).
+              If  the  interlace type 0 is selected, the output image shall be
+              non-interlaced (i.e. progressive-scanned). If the interlace type
+              1 is selected, the output image shall be  interlaced  using  the
+              Adam7 method.
+              By default, the output shall have the same interlace type as the
+              input.
+
+       -nb    Do not apply bit depth reduction.
+
+       -nc    Do not apply color type reduction.
+
+       -np    Do not apply palette reduction.
+
+       -nx    Do  not  apply  any lossless image reduction: enable the options
+              -nb, -nc and -np.
+
+       -nz    Do not recode IDAT datastreams.
+              The IDAT optimization operations that do  not  require  recoding
+              (e.g. IDAT chunk concatenation) are still performed.
+              This option has effect on PNG input files only.
+
+       -zc levels
+              Select the zlib compression levels used in IDAT compression.
+              The  levels  argument  is specified as a rangeset (e.g. -zc6-9),
+              and the default levels value depends on the  optimization  level
+              set by the option -o.
+              The effect of this option is defined by the zlib(3) library used
+              by OptiPNG.
+
+       -zm levels
+              Select the zlib memory levels used in IDAT compression.
+              The  levels  argument  is specified as a rangeset (e.g. -zm8-9),
+              and the default levels value depends on the  optimization  level
+              set by the option -o.
+              The effect of this option is defined by the zlib(3) library used
+              by OptiPNG.
+
+       -zs strategies
+              Select the zlib compression strategies used in IDAT compression.
+              The  strategies  argument  is  specified  as  a  rangeset  (e.g.
+              -zs0-3), and the default strategies value depends on  the  opti-
+              mization level set by the option -o.
+              The effect of this option is defined by the zlib(3) library used
+              by OptiPNG.
+
+       -zw size
+              Select  the  zlib window size (32k,16k,8k,4k,2k,1k,512,256) used
+              in IDAT compression.
+              The size argument can be specified either in bytes (e.g.  16384)
+              or  kilobytes  (e.g.  16k). The default size value is set to the
+              lowest window size that yields an  IDAT  output  as  big  as  if
+              yielded by the value 32768.
+              The effect of this option is defined by the zlib(3) library used
+              by OptiPNG.
+
+   Editing options
+       -snip  Cut one image out of multi-image, animation or video files.
+              Depending  on  the input format, this may be either the first or
+              the most relevant (e.g. the largest) image.
+
+       -strip objects
+              Strip metadata objects from a PNG file.
+              PNG metadata is the information stored in  any  ancillary  chunk
+              except tRNS.  (tRNS represents the alpha channel, which, even if
+              ignored  in  rendering,  is  still a proper image channel in the
+              RGBA color space.)
+              The only option currently supported is -strip all.
+
+   Notes
+       Options may come in any order (except for --), before, after, or alter-
+       nating with file names. Option names are case-insensitive  and  may  be
+       abbreviated to their shortest unique prefix.
+
+       Some  options may have arguments that follow the option name, separated
+       by whitespace or the equal sign ('='). If the option argument is a num-
+       ber or a rangeset, the separator may be omitted. For example:
+
+              -out newfile.png  <=>  -out=newfile.png
+              -o3  <=>  -o 3  <=>  -o=3
+              -f0,3-5  <=>  -f 0,3-5  <=>  -f=0,3-5
+
+       Rangeset arguments are cumulative; e.g.
+
+              -f0 -f3-5  <=>  -f0,3-5
+              -zs0 -zs1 -zs2-3  <=>  -zs0,1,2,3  <=>  -zs0-3
+
+EXTENDED DESCRIPTION
+       The PNG optimization algorithm consists of the following steps:
+
+       1.  Reduce the bit depth, the color type and the color palette  of  the
+           image.   This  step  may reduce the size of the uncompressed image,
+           which, indirectly, may reduce the  size  of  the  compressed  image
+           (i.e. the size of the output PNG file).
+
+       2.  Run  a  suite  of compression methods and strategies and select the
+           compression parameters that yield the smallest output file.
+
+       3.  Store all IDAT contents into a single chunk, eliminating the  over-
+           head incurred by repeated IDAT headers and CRCs.
+
+       4.  Set the zlib window size inside IDAT to a mininum that does not af-
+           fect the compression ratio, reducing the memory requirements of PNG
+           decoders.
+
+       Not all of the above steps need to be executed. The behavior depends on
+       the actual input files and user options.
+
+       Step  1  may  be customized via the no-reduce options -nb, -nc, -np and
+       -nx. Step 2 may be customized via the -o option, and may be  fine-tuned
+       via  the options -zc, -zm, -zs and -zw. Step 3 is always executed. Step
+       4 is executed only if a new IDAT is being created,  and  may  be  fine-
+       tuned via the option -zw.
+
+       Extremely  exhaustive searches are not generally expected to yield sig-
+       nificant improvements in compression ratio, and are recommended to  ad-
+       vanced users only.
+
+EXAMPLES
+       optipng file.png      # default speed
+       optipng -o5 file.png  # slow
+       optipng -o7 file.png  # very slow
+
+BUGS
+       Lossless  image  reductions are not completely implemented.  (This does
+       not affect the integrity of the output files.)  Here  are  the  missing
+       pieces:
+
+              - The color palette reductions are implemented only partially.
+              -  The  bit  depth reductions below 8, for grayscale images, are
+              not implemented yet.
+
+       Encoding of images whose total IDAT size exceeds 2GB is not supported.
+
+       TIFF support is limited to uncompressed, PNG-compatible (grayscale, RGB
+       and RGBA) images.
+
+       Metadata is not imported from the external image formats.
+
+       There is no support for pipes, streams, extended file attributes or ac-
+       cess control lists.
+
+SEE ALSO
+       png(5), libpng(3), zlib(3), pngcrush(1), pngrewrite(1).
+
+STANDARDS
+       The files produced by OptiPNG are compliant with PNG-2003:
+       Glenn Randers-Pehrson et al.  Portable Network Graphics (PNG)  Specifi-
+       cation, Second Edition.
+       W3C Recommendation 10 November 2003; ISO/IEC IS 15948:2003 (E).
+       http://www.w3.org/TR/PNG/
+
+AUTHOR
+       OptiPNG is written and maintained by Cosmin Truta.
+
+       This  manual  page  was originally written by Nelson A. de Oliveira for
+       the Debian Project. It was later updated by Cosmin Truta,  and  is  now
+       part of the OptiPNG distribution.
+
+OptiPNG version 0.7.8             2023-Nov-03                       OPTIPNG(1)
diff --git a/doc/optipng-0.7.8-win64/doc/todo.txt b/doc/optipng-0.7.8-win64/doc/todo.txt
new file mode 100644
index 00000000000..f4a6c1b80aa
--- /dev/null
+++ b/doc/optipng-0.7.8-win64/doc/todo.txt
@@ -0,0 +1,42 @@
+OptiPNG - TO-DO list
+====================
+
+- Compression improvements:
+  Use zlib's deflateTune().
+  Use 7zip's and/or zopfli's powerful deflation engine.
+
+- Speed improvements:
+  Avoid repeated filtering when trying a filter value more than once.
+
+- Text chunk optimization:
+  Smart selection between tEXt and zTXt.
+  Smart selection between uncompressed iTXt and compressed iTXt.
+
+- Improved support for reading external image formats
+  (e.g. compressed TIFF).
+
+- More file recovery features.
+
+- Input from stdin; output to stdout:
+    cat infile | optipng > outfile
+    optipng -stdout infile > outfile
+
+- Optimization of an entire directory, with and without subdirectory
+  recursion:
+    optipng dir/
+    optipng -recursive dir/
+
+- Support for conversion to a desired bit depth and color type:
+    optipng -b16 -c6 files ...
+
+- Support for handling metadata, e.g.:
+    optipng -set tEXt=<keyword>,<text>     # add or update chunk
+    optipng -set sRGB=0                    # add or update chunk
+    optipng -set image.precision=<n>       # set the precision of all samples
+    optipng -set image.alpha.precision=<n> # set the precision of alpha samples
+    optipng -reset image.alpha             # make the image fully opaque
+    optipng -strip hIST,sPLT               # strip hIST and sPLT
+    optipng -strip all -protect iCCP       # strip all metadata except iCCP
+
+- Parallelization on multi-processor/multi-core machines:
+    optipng -jobs 4 files ...
diff --git a/doc/optipng-0.7.8-win64/optipng.exe b/doc/optipng-0.7.8-win64/optipng.exe
new file mode 100644
index 0000000000000000000000000000000000000000..76920bad2dc1340a9e1dad6a34d64f29fda7f183
GIT binary patch
diff --git a/tutorials/intro/70_report.py b/tutorials/intro/70_report.py
index 7fe30ff6b96..b44d44f09f8 100644
--- a/tutorials/intro/70_report.py
+++ b/tutorials/intro/70_report.py
@@ -6,698 +6,266 @@
 ===============================
 
 :class:`mne.Report` is a way to create interactive HTML summaries of your data.
-These reports can show many different visualizations for one or multiple participants.
-A common use case is creating diagnostic summaries to check data quality at different
-stages in the processing pipeline. The report can show things like plots of data before
-and after each preprocessing step, epoch rejection statistics, MRI slices with overlaid
-BEM shells, all the way up to plots of estimated cortical activity.
-
-Compared to a Jupyter notebook, :class:`mne.Report` is easier to deploy, as the HTML
-pages it generates are self-contained and do not require a running Python environment.
-However, it is less flexible as you can't change code and re-run something directly
-within the browser. This tutorial covers the basics of building a report. As usual,
-we will start by importing the modules and data we need:
+These reports can show many different visualizations for one or multiple
+participants. A common use case is creating diagnostic summaries to check data
+quality at different stages in the processing pipeline. The report can show
+things like plots of data before and after each preprocessing step, epoch
+rejection statistics, MRI slices with overlaid BEM shells, all the way up to
+plots of estimated cortical activity.
+
+Compared to a Jupyter notebook, :class:`mne.Report` is easier to deploy, as the
+HTML pages it generates are self-contained and do not require a running Python
+environment. However, it is less flexible as you can't change code and re-run
+something directly within the browser. This tutorial covers the basics of
+building a report.
+
+This tutorial demonstrates how to generate a full MNE-Python report combining:
+- Quality Control (QC) steps: raw data, PSD, events, epochs, ICA
+- Full MNE diagnostics: covariance, projectors, BEM, coregistration,
+  forward/inverse solutions, source estimates
+- Custom figures and HTML content
 """
 
 # Authors: The MNE-Python contributors.
 # License: BSD-3-Clause
 # Copyright the MNE-Python contributors.
 
-# %%
 
-import tempfile
+# This block imports all the Python libraries we need. These include MNE for M/EEG
+# processing, NumPy for numerical operations, Matplotlib for plotting, and
+# Pathlib for handling file paths. They provide all the basic tools required to
+# load data, run QC, create figures, and build the final HTML report.
+
 from pathlib import Path
 
 import matplotlib.pyplot as plt
 import numpy as np
-import scipy.ndimage
 
 import mne
+from mne.preprocessing import ICA
+
+"""
+Here we load the MNE sample dataset, which contains raw data, events, evoked
+responses, and anatomical files. Using this dataset allows us to demonstrate how
+to generate a full QC + MNE report without requiring your own data.
+"""
 
 data_path = Path(mne.datasets.sample.data_path(verbose=False))
 sample_dir = data_path / "MEG" / "sample"
 subjects_dir = data_path / "subjects"
 
-# %%
-# The basic process for creating an HTML report is to instantiate the
-# :class:`~mne.Report` class and then use one or more of its many methods to
-# add content, one element at a time.
-#
-# You may also use the :meth:`~mne.Report.parse_folder` method to select
-# particular files to include in the report. But more on that later.
-#
-# .. sidebar: Viewing the report
-#
-#    On successful creation of the report, the :meth:`~mne.Report.save` method
-#    will open the HTML in a new tab in your browser. To disable this, use the
-#    ``open_browser=False`` parameter of :meth:`~mne.Report.save`.
-#
-# Adding `~mne.io.Raw` data
-# ^^^^^^^^^^^^^^^^^^^^^^^^^
-#
-# Raw data can be added via the :meth:`mne.Report.add_raw` method. It can
-# operate with a path to a raw file and `~mne.io.Raw` objects, and will
-# produce – among other output – a slider that allows you to scrub through 10
-# equally-spaced 1-second segments of the data:
-#
-# .. warning::
-#    In the following example, we crop the raw data to 60 seconds merely to
-#    speed up processing; this is not usually recommended!
-
-raw_path = sample_dir / "sample_audvis_filt-0-40_raw.fif"
-raw = mne.io.read_raw(raw_path)
-raw.pick(picks=["eeg", "eog", "stim"]).crop(tmax=60).load_data()
-
-report = mne.Report(title="Raw example")
-# This method also accepts a path, e.g., raw=raw_path
-report.add_raw(raw=raw, title="Raw", psd=False)  # omit PSD plot
-report.save("report_raw.html", overwrite=True)
-
-# %%
-# Adding events
-# ^^^^^^^^^^^^^
-#
-# Events can be added via :meth:`mne.Report.add_events`. You also need to
-# supply the sampling frequency used during the recording; this information is
-# used to generate a meaningful time axis.
-
-events_path = sample_dir / "sample_audvis_filt-0-40_raw-eve.fif"
-events = mne.find_events(raw=raw)
-sfreq = raw.info["sfreq"]
-
-report = mne.Report(title="Events example")
-report.add_events(events=events_path, title="Events from Path", sfreq=sfreq)
-report.add_events(events=events, title='Events from "events"', sfreq=sfreq)
-report.save("report_events.html", overwrite=True)
-
-# %%
-# Adding :class:`~mne.Epochs`
-# ^^^^^^^^^^^^^^^^^^^^^^^^^^^
-#
-# Epochs can be added via :meth:`mne.Report.add_epochs`. Note that although
-# this method accepts a path to an epochs file too, in the following example
-# we only add epochs that we create on the fly from raw data. To demonstrate
-# the representation of epochs metadata, we'll add some of that, too.
-
-event_id = {
-    "auditory/left": 1,
-    "auditory/right": 2,
-    "visual/left": 3,
-    "visual/right": 4,
-    "face": 5,
-    "buttonpress": 32,
-}
-
-metadata, _, _ = mne.epochs.make_metadata(
-    events=events, event_id=event_id, tmin=-0.2, tmax=0.5, sfreq=raw.info["sfreq"]
-)
-epochs = mne.Epochs(raw=raw, events=events, event_id=event_id, metadata=metadata)
-
-report = mne.Report(title="Epochs example")
-report.add_epochs(epochs=epochs, title='Epochs from "epochs"')
-report.save("report_epochs.html", overwrite=True)
-
-# %%
-# Adding `~mne.Evoked`
-# ^^^^^^^^^^^^^^^^^^^^
-#
-# Evoked data can be added via :meth:`mne.Report.add_evokeds`. By default, the
-# ``Evoked.comment`` attribute of each evoked will be used as a title. We can
-# specify custom titles via the ``titles`` parameter. Again, this method
-# also accepts the path to an evoked file stored on disk; in the following
-# example, however, we load the evokeds manually first, since we only want to
-# add a subset of them to the report. The evokeds are not baseline-corrected, so we
-# apply baseline correction, too. Lastly, by providing an (optional) noise covariance,
-# we can add plots evokeds that were "whitened" using this covariance matrix.
-#
-# By default, this method will produce topographic plots at 21 equally-spaced time
-# points (or fewer, if the data contains fewer time points). We can adjust this
-# via the ``n_time_points`` parameter.
-
-evoked_path = sample_dir / "sample_audvis-ave.fif"
-cov_path = sample_dir / "sample_audvis-cov.fif"
-
-evokeds = mne.read_evokeds(evoked_path, baseline=(None, 0))
-evokeds_subset = evokeds[:2]  # The first two
-for evoked in evokeds_subset:
-    evoked.pick("eeg")  # just for speed of plotting
-
-report = mne.Report(title="Evoked example")
-report.add_evokeds(
-    evokeds=evokeds_subset,
-    titles=["evoked 1", "evoked 2"],  # Manually specify titles
-    noise_cov=cov_path,
-    n_time_points=5,
-)
-report.save("report_evoked.html", overwrite=True)
-
-# %%
-# Adding `~mne.Covariance`
-# ^^^^^^^^^^^^^^^^^^^^^^^^
-#
-# (Noise) covariance objects can be added via
-# :meth:`mne.Report.add_covariance`. The method accepts `~mne.Covariance`
-# objects and the path to a file on disk. It also expects us to pass an
-# `~mne.Info` object or the path to a file to read the measurement info from,
-# as well as a title.
-
-cov_path = sample_dir / "sample_audvis-cov.fif"
-
-report = mne.Report(title="Covariance example")
-report.add_covariance(cov=cov_path, info=raw_path, title="Covariance")
-report.save("report_cov.html", overwrite=True)
-
-# %%
-# Adding `~mne.Projection` vectors
-# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-#
-# `~mne.Projection` vectors can be added via
-# :meth:`mne.Report.add_projs`. The method requires an `~mne.Info` object
-# (or the path to one) and a title. Projectors found in the `~mne.Info` will
-# be visualized. You may also supply a list of `~mne.Projection` objects or
-# a path to projectors stored on disk. In this case, the channel information
-# is read from the `~mne.Info`, but projectors potentially included will be
-# ignored; instead, only the explicitly passed projectors will be plotted.
-
-ecg_proj_path = sample_dir / "sample_audvis_ecg-proj.fif"
-report = mne.Report(title="Projectors example")
-report.add_projs(info=raw_path, title="Projs from info")
-
-# Now a joint plot
-events = mne.read_events(sample_dir / "sample_audvis_ecg-eve.fif")
-raw_full = mne.io.read_raw(sample_dir / "sample_audvis_raw.fif").crop(0, 60).load_data()
-ecg_evoked = mne.Epochs(
-    raw=raw_full,
-    events=events,
-    tmin=-0.5,
+raw_fname = sample_dir / "sample_audvis_raw.fif"
+events_fname = sample_dir / "sample_audvis_raw-eve.fif"
+evoked_fname = sample_dir / "sample_audvis-ave.fif"
+cov_fname = sample_dir / "sample_audvis-cov.fif"
+fwd_fname = sample_dir / "sample_audvis-meg-oct-6-fwd.fif"
+inv_fname = sample_dir / "sample_audvis-meg-oct-6-meg-inv.fif"
+trans_fname = sample_dir / "sample_audvis_raw-trans.fif"
+proj_fname = sample_dir / "sample_audvis_ecg-proj.fif"
+
+raw = mne.io.read_raw_fif(raw_fname, preload=True)
+raw.pick_types(meg=True, eeg=True, eog=True, stim=True)
+
+events = mne.read_events(events_fname)
+
+"""
+This function makes a simple static plot of the first few seconds of raw data.
+It avoids the interactive browser and instead gives a quick visual check of
+signal quality, channel behavior, and overall data shape, which is important for
+QC reports.
+"""
+
+
+def make_raw_overview_figure(raw, n_channels=20, duration=10):
+    """Create a Matplotlib-only raw overview."""
+    sfreq = raw.info["sfreq"]
+    start = 0
+    stop = int(duration * sfreq)
+
+    data, times = raw.get_data(start=start, stop=stop, return_times=True)
+    n = min(n_channels, data.shape[0])
+    data = data[:n]
+    data_norm = data / np.max(np.abs(data), axis=1, keepdims=True)
+
+    fig, ax = plt.subplots(figsize=(12, 6))
+    offset = np.arange(n) * 1.5
+    for i in range(n):
+        ax.plot(times, data_norm[i] + offset[i])
+    ax.set_title(f"Raw Data Overview ({n} channels, {duration}s)")
+    ax.set_xlabel("Time (s)")
+    ax.set_ylabel("Channels (offset)")
+    return fig
+
+
+"""
+We create the MNE Report object and add basic QC components: a simple raw
+overview, the power spectral density (PSD) plot, and the sensor layout. These
+plots help verify noise levels, channel availability, and general data quality
+before deeper analysis.
+"""
+
+report = mne.Report(title="QC + Full MNE Report (Clean, No Duplicates)")
+
+fig = make_raw_overview_figure(raw)
+report.add_figure(fig, title="Raw Data Overview")
+plt.close(fig)
+
+psd = raw.compute_psd()
+fig = psd.plot(show=False)
+report.add_figure(fig, title="PSD of Raw Data")
+plt.close(fig)
+
+fig = raw.plot_sensors(show_names=True)
+report.add_figure(fig, title="Sensor Layout")
+plt.close(fig)
+
+"""
+This block loads event markers and creates epochs (short time windows around
+stimulus events). Epochs allow us to check data quality trial-by-trial and
+understand how different conditions were recorded, which is essential in QC.
+"""
+
+event_id = dict(auditory=1, visual=3)
+report.add_events(events, sfreq=raw.info["sfreq"], title="Events Overview")
+
+epochs = mne.Epochs(
+    raw,
+    events,
+    event_id=event_id,
+    tmin=-0.2,
     tmax=0.5,
-    baseline=(None, None),
-).average()
-report.img_max_width = None  # do not constrain image width
-report.add_projs(
-    info=ecg_evoked,
-    projs=ecg_proj_path,
-    title="ECG projs from path",
-    joint=True,  # use joint version of the plot
-)
-report.save("report_projs.html", overwrite=True)
-del raw_full, events, ecg_evoked
-
-# %%
-# Adding `~mne.preprocessing.ICA`
-# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-#
-# `~mne.preprocessing.ICA` objects can be added via
-# :meth:`mne.Report.add_ica`. Aside from the parameters ``ica`` (that accepts
-# an `~mne.preprocessing.ICA` instance or a path to an ICA object stored on
-# disk) and the ``title``, there is a third required parameter, ``inst``.
-# ``inst`` is used to specify a `~mne.io.Raw` or `~mne.Epochs` object for
-# producing ICA property plots and overlay plots demonstrating
-# the effects of ICA cleaning. If, instead, you only want to generate ICA
-# component topography plots, explicitly pass ``inst=None``.
-#
-# .. note:: :meth:`mne.Report.add_ica` only works with fitted ICAs.
-#
-# You can optionally specify for which components to produce topography and
-# properties plots by passing ``picks``. By default, all components will be
-# shown. It is also possible to pass evoked signals based on ECG and EOG events
-# via ``ecg_evoked`` and ``eog_evoked``. This allows you directly see the
-# effects of ICA component removal on these artifactual signals.
-# Artifact detection scores produced by
-# :meth:`~mne.preprocessing.ICA.find_bads_ecg`
-# and :meth:`~mne.preprocessing.ICA.find_bads_eog` can be passed via the
-# ``ecg_scores`` and ``eog_scores`` parameters, respectively, producing
-# visualizations of the scores for each ICA component.
-#
-# Lastly, by passing ``n_jobs``, you may largely speed up the generation of
-# the properties plots by enabling parallel execution.
-#
-# .. warning::
-#    In the following example, we request a small number of ICA components
-#    to estimate, set the threshold for assuming ICA convergence to a very
-#    liberal value, and only visualize 2 of the components. All of this is
-#    done to largely reduce the processing time of this tutorial, and is
-#    usually **not** recommended for an actual data analysis.
-
-ica = mne.preprocessing.ICA(
-    n_components=5,  # fit 5 ICA components
-    fit_params=dict(tol=0.01),  # assume very early on that ICA has converged
+    baseline=(None, 0),
+    preload=True,
+    reject=dict(mag=4e-12, eeg=150e-6),
 )
+report.add_epochs(epochs, title="Epochs Overview")
 
-ica.fit(inst=raw)
+"""
+Here we fit ICA to identify eye-movement components and mark them for removal.
+We also add ICA diagnostics to the report, such as component maps and EOG
+correlations. ICA is an important step in QC for detecting common artifacts.
+"""
 
-# create epochs based on EOG events, find EOG artifacts in the data via pattern
-# matching, and exclude the EOG-related ICA components
-eog_epochs = mne.preprocessing.create_eog_epochs(raw=raw)
-eog_components, eog_scores = ica.find_bads_eog(
-    inst=eog_epochs,
-    ch_name="EEG 001",  # a channel close to the eye
-    threshold=1,  # lower than the default threshold
-)
-ica.exclude = eog_components
+ica = ICA(n_components=20, random_state=97)
+ica.fit(raw)
+
+eog_epochs = mne.preprocessing.create_eog_epochs(raw)
+eog_comps, eog_scores = ica.find_bads_eog(eog_epochs, ch_name="EEG 001")
+ica.exclude = eog_comps
 
-report = mne.Report(title="ICA example")
 report.add_ica(
     ica=ica,
-    title="ICA cleaning",
-    picks=ica.exclude,  # plot the excluded EOG components
     inst=raw,
+    title="ICA Components",
     eog_evoked=eog_epochs.average(),
     eog_scores=eog_scores,
-    n_jobs=None,  # could be increased!
-)
-report.save("report_ica.html", overwrite=True)
-
-# %%
-# Adding MRI with BEM
-# ^^^^^^^^^^^^^^^^^^^
-#
-# MRI slices with superimposed traces of the boundary element model (BEM)
-# surfaces can be added via :meth:`mne.Report.add_bem`. All you need to pass is
-# the FreeSurfer subject name and subjects directory, and a title. To reduce
-# the resulting file size, you may pass the ``decim`` parameter to only include
-# every n-th volume slice, and ``width`` to specify the width of the resulting
-# figures in pixels.
-
-report = mne.Report(title="BEM example")
-report.add_bem(
-    subject="sample",
-    subjects_dir=subjects_dir,
-    title="MRI & BEM",
-    decim=40,
-    width=256,
 )
-report.save("report_mri_and_bem.html", overwrite=True)
-
-# %%
-# Adding coregistration
-# ^^^^^^^^^^^^^^^^^^^^^
-#
-# The sensor alignment (``head -> mri`` transformation obtained by
-# "coregistration") can be visualized via :meth:`mne.Report.add_trans`. The
-# method expects the transformation either as a `~mne.transforms.Transform`
-# object or as a path to a ``trans.fif`` file, the FreeSurfer subject name and
-# subjects directory, and a title. The ``alpha`` parameter can be used to
-# control the transparency of the head, where a value of 1 means fully opaque.
-
-trans_path = sample_dir / "sample_audvis_raw-trans.fif"
-
-report = mne.Report(title="Coregistration example")
-report.add_trans(
-    trans=trans_path,
-    info=raw_path,
-    subject="sample",
-    subjects_dir=subjects_dir,
-    alpha=1.0,
-    title="Coregistration",
+
+"""
+This section computes evoked responses (averaged brain activity) for auditory and
+visual events and plots topographic maps. It also loads the noise covariance
+matrix and any projectors. Together, these help evaluate data cleanliness and
+prepare for source analysis.
+"""
+
+cov = mne.read_cov(cov_fname)
+evokeds = [epochs[k].average() for k in event_id]
+report.add_evokeds(
+    evokeds, titles=list(event_id.keys()), noise_cov=cov, n_time_points=5
 )
-report.save("report_coregistration.html", overwrite=True)
 
-# %%
-# Adding a `~mne.Forward` solution
-# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-#
-# Forward solutions ("leadfields") can be added by passing a `~mne.Forward`
-# object or the path to a forward solution stored on disk to
-# meth:`mne.Report.add_forward`.
+common_chs = list(set(cov.ch_names).intersection(raw.ch_names))
+cov = cov.copy().pick_channels(common_chs)
+report.add_covariance(cov=cov, info=raw.info, title="Noise Covariance")
 
-fwd_path = sample_dir / "sample_audvis-meg-oct-6-fwd.fif"
+projs = mne.read_proj(proj_fname)
+report.add_projs(info=raw, projs=projs, title="ECG Projectors")
 
-report = mne.Report(title="Forward solution example")
-report.add_forward(
-    forward=fwd_path, title="Forward solution", plot=True, subjects_dir=subjects_dir
-)
-report.save("report_forward_sol.html", overwrite=True)
-
-# %%
-# Adding an `~mne.minimum_norm.InverseOperator`
-# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-#
-# An inverse operator can be added via :meth:`mne.Report.add_inverse_operator`.
-# The method expects an `~mne.minimum_norm.InverseOperator` object or a path to
-# one stored on disk, and a title.
-
-inverse_op_path = sample_dir / "sample_audvis-meg-oct-6-meg-inv.fif"
-
-report = mne.Report(title="Inverse operator example")
-report.add_inverse_operator(
-    inverse_operator=inverse_op_path,
-    title="Inverse operator",
-    plot=True,
-    subjects_dir=subjects_dir,
-)
-report.save("report_inverse_op.html", overwrite=True)
-
-# %%
-# Adding a `~mne.SourceEstimate`
-# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-#
-# An inverse solution (also called source estimate or source time course, STC)
-# can be added via :meth:`mne.Report.add_stc`. The
-# method expects an `~mne.SourceEstimate`, the corresponding FreeSurfer subject
-# name and subjects directory, and a title. By default, it will produce
-# snapshots at 51 equally-spaced time points (or fewer, if the data contains
-# fewer time points). We can adjust this via the ``n_time_points`` parameter.
-
-stc_path = sample_dir / "sample_audvis-meg"
-
-report = mne.Report(title="Source estimate example")
-report.add_stc(
-    stc=stc_path,
-    subject="sample",
-    subjects_dir=subjects_dir,
-    title="Source estimate",
-    n_time_points=2,  # few for speed
-)
-report.save("report_inverse_sol.html", overwrite=True)
-
-# %%
-# Adding source code (e.g., a Python script)
-# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-#
-# It is possible to add code or scripts (e.g., the scripts you used for
-# analysis) to the report via :meth:`mne.Report.add_code`. The code blocks will
-# be automatically syntax-highlighted. You may pass a string with the
-# respective code snippet, or the path to a file. If you pass a path, it
-# **must** be a `pathlib.Path` object (and not a string), otherwise it will be
-# treated as a code literal.
-#
-# Optionally, you can specify which programming language to assume for syntax
-# highlighting by passing the ``language`` parameter. By default, we'll assume
-# the provided code is Python.
-
-mne_init_py_path = Path(mne.__file__)  # __init__.py in the MNE-Python root
-mne_init_py_content = mne_init_py_path.read_text(encoding="utf-8")
-
-report = mne.Report(title="Code example")
-report.add_code(code=mne_init_py_path, title="Code from Path")
-report.add_code(code=mne_init_py_content, title="Code from string")
-
-report.save("report_code.html", overwrite=True)
-
-# %%
-# Adding custom figures
-# ^^^^^^^^^^^^^^^^^^^^^
-#
-# Custom Matplotlib figures can be added via :meth:`~mne.Report.add_figure`.
-# Required parameters are the figure and a title. Optionally, may add a caption
-# to appear below the figure. You can also specify the image format of the
-# image file that will be generated from the figure, so it can be embedded in
-# the HTML report.
-
-x = np.linspace(start=0, stop=10, num=100)
-y = x**2
-
-fig, ax = plt.subplots()
-ax.plot(x, y, ls="--", lw=2, color="blue", label="my function")
-ax.set_xlabel("x")
-ax.set_ylabel("f(x)")
-ax.legend()
-
-report = mne.Report(title="Figure example")
-report.add_figure(
-    fig=fig,
-    title="A custom figure",
-    caption="A blue dashed line reaches up into the sky …",
-    image_format="PNG",
-)
-report.save("report_custom_figure.html", overwrite=True)
-plt.close(fig)
+"""
+Here we try adding anatomical elements like the MRI surfaces (BEM),
+sensor-to-MRI coregistration, and the forward and inverse operators. These steps
+link sensor data to the brain and are needed for source estimation. They are
+wrapped in try/except so the script still runs even if anatomy files are
+missing.
+"""
 
-# %%
-# Multiple figures can be grouped into a single section via the ``section``
-# parameter.
-
-fig_1, ax_1 = plt.subplots()
-ax_1.plot([1, 2, 3])
-
-fig_2, ax_2 = plt.subplots()
-ax_2.plot([3, 2, 1])
-
-section = "Section example"
-
-report = mne.Report(title="Figure section example")
-report.add_figure(fig=fig_1, title="Figure 1", section=section, tags="fig-1")
-report.add_figure(fig=fig_2, title="Figure 2", section=section, tags="fig-2")
-report.save("report_custom_figure_sections.html", overwrite=True)
-plt.close(fig_1)
-plt.close(fig_2)
-
-# %%
-# The :meth:`mne.Report.add_figure` method can also add multiple figures at
-# once. In this case, a slider will appear, allowing users to intuitively
-# browse the figures. To make this work, you need to provide a collection o
-# figures, a title, and optionally a collection of captions.
-#
-# In the following example, we will read the MNE logo as a Matplotlib figure
-# and rotate it with different angles. Each rotated figure and its respective
-# caption will be added to a list, which is then used to create the slider.
-
-mne_logo_path = Path(mne.__file__).parent / "icons" / "mne_icon-cropped.png"
-fig_array = plt.imread(mne_logo_path)
-rotation_angles = np.linspace(start=0, stop=360, num=8, endpoint=False)
-
-figs = []
-captions = []
-for angle in rotation_angles:
-    # Rotate and remove some rounding errors to avoid Matplotlib warnings
-    fig_array_rotated = scipy.ndimage.rotate(input=fig_array, angle=angle)
-    fig_array_rotated = fig_array_rotated.clip(min=0, max=1)
-
-    # Create the figure
-    fig, ax = plt.subplots(figsize=(3, 3), layout="constrained")
-    ax.imshow(fig_array_rotated)
-    ax.set_axis_off()
-
-    # Store figure and caption
-    figs.append(fig)
-    captions.append(f"Rotation angle: {round(angle, 1)}°")
-
-report = mne.Report(title="Multiple figures example")
-report.add_figure(fig=figs, title="Fun with figures! 🥳", caption=captions)
-report.save("report_custom_figures.html", overwrite=True)
-for fig in figs:
-    plt.close(fig)
-del figs
-
-# %%
-# Adding image files
-# ^^^^^^^^^^^^^^^^^^
-#
-# Existing images (e.g., photos, screenshots, sketches etc.) can be added
-# to the report via :meth:`mne.Report.add_image`. Supported image formats
-# include JPEG, PNG, GIF, and SVG (and possibly others). Like with Matplotlib
-# figures, you can specify a caption to appear below the image.
-
-report = mne.Report(title="Image example")
-report.add_image(
-    image=mne_logo_path, title="MNE", caption="Powered by 🧠 🧠 🧠 around the world!"
-)
-report.save("report_custom_image.html", overwrite=True)
-
-# %%
-# Working with tags
-# ^^^^^^^^^^^^^^^^^
-#
-# Each ``add_*`` method accepts a keyword parameter ``tags``, which can be
-# used to pass one or more tags to associate with the respective content
-# elements. By default, each ``add_*`` method adds a tag describing the data
-# type, e.g., ``evoked`` or ``source-estimate``. When viewing the HTML report,
-# the ``Filter by tags`` dropdown menu can be used to interactively show or
-# hide content with specific tags. This allows you e.g. to only view
-# ``evoked`` or ``participant-001`` data, should you have added those tags.
-# Visible tags will appear with blue, and hidden tags with gray background
-# color.
-#
-# To toggle the visibility of **all** tags, use the respective checkbox in the
-# ``Filter by tags`` dropdown menu, or press :kbd:`T`.
-
-report = mne.Report(title="Tags example")
-report.add_image(
-    image=mne_logo_path,
-    title="MNE Logo",
-    tags=("image", "mne", "logo", "open-source"),
-)
-report.save("report_tags.html", overwrite=True)
-
-# %%
-# Editing a saved report
-# ^^^^^^^^^^^^^^^^^^^^^^
-#
-# Saving to HTML is a write-only operation, meaning that we cannot read an
-# ``.html`` file back as a :class:`~mne.Report` object. In order to be able
-# to edit a report once it's no longer in-memory in an active Python session,
-# save it as an HDF5 file instead of HTML:
-
-report = mne.Report(title="Saved report example", verbose=True)
-report.add_image(image=mne_logo_path, title="MNE 1")
-report.save("report_partial.hdf5", overwrite=True)
-
-# %%
-# The saved report can be read back and modified or amended. This allows the
-# possibility to e.g. run multiple scripts in a processing pipeline, where each
-# script adds new content to an existing report.
-
-report_from_disk = mne.open_report("report_partial.hdf5")
-report_from_disk.add_image(image=mne_logo_path, title="MNE 2")
-report_from_disk.save("report_partial.hdf5", overwrite=True)
-
-# %%
-# To make this even easier, :class:`mne.Report` can be used as a
-# context manager (note the ``with`` statement)`):
-
-with mne.open_report("report_partial.hdf5") as report:
-    report.add_image(image=mne_logo_path, title="MNE 3")
-    report.save("report_final.html", overwrite=True)
-
-# %%
-# With the context manager, the updated report is also automatically saved
-# back to :file:`report.h5` upon leaving the block.
-#
-# Adding an entire folder of files
-# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-#
-# We also provide a way to add an entire **folder** of files to the report at
-# once, without having to invoke the individual ``add_*`` methods outlined
-# above for each file. This approach, while convenient, provides less
-# flexibility with respect to content ordering, tags, titles, etc.
-#
-# Before getting started with :class:`mne.Report`, make sure the files you want
-# to render follow the filename conventions defined by MNE:
-#
-# .. cssclass:: table-bordered
-# .. rst-class:: midvalign
-#
-# =================================== =========================================
-# Data object                         Filename convention (ends with)
-# =================================== =========================================
-# `~mne.io.Raw`                       ``-raw.fif(.gz)``, ``-raw_sss.fif(.gz)``,
-#                                     ``-raw_tsss.fif(.gz)``,
-#                                     ``_meg.fif(.gz)``, ``_eeg.fif(.gz)``,
-#                                     ``_ieeg.fif(.gz)``
-# events                              ``-eve.fif(.gz)``
-# `~mne.Epochs`                       ``-epo.fif(.gz)``
-# `~mne.Evoked`                       ``-ave.fif(.gz)``
-# `~mne.Covariance`                   ``-cov.fif(.gz)``
-# `~mne.Projection`                   ``-proj.fif(.gz)``
-# `~mne.transforms.Transform`         ``-trans.fif(.gz)``
-# `~mne.Forward`                      ``-fwd.fif(.gz)``
-# `~mne.minimum_norm.InverseOperator` ``-inv.fif(.gz)``
-# `~mne.SourceEstimate`               ``-lh.stc``, ``-rh.stc``
-# =================================== =========================================
-#
-# Alternatively, the dash ``-`` in the filename may be replaced with an
-# underscore ``_`` (except for the ``.stc`` files).
-#
-# For our first example, we'll 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`
-# constructor, but we'll also pass ``render_bem=False`` to the
-# :meth:`~mne.Report.parse_folder` method — otherwise we would get a warning
-# about not being able to render MRI and ``trans`` files without knowing the
-# subject. To save some processing time in this tutorial, we're also going to
-# disable rendering of the butterfly plots for the `~mne.io.Raw` data by
-# passing ``raw_butterfly=False``.
-#
-# Which files are included depends on both the ``pattern`` parameter passed to
-# :meth:`~mne.Report.parse_folder` and also the ``subject`` and
-# ``subjects_dir`` parameters provided to the :class:`~mne.Report` constructor.
-
-report = mne.Report(title="parse_folder example")
-report.parse_folder(
-    data_path=data_path, pattern="*raw.fif", render_bem=False, raw_butterfly=False
-)
-report.save("report_parse_folder_basic.html", overwrite=True)
-
-# %%
-# By default, the power spectral density and SSP projectors of the
-# :class:`~mne.io.Raw` files are not shown to speed up report generation. You
-# can add them by passing ``raw_psd=True`` and ``projs=True`` to the
-# :class:`~mne.Report` constructor. Like in the previous example, we're going
-# to omit the butterfly plots by passing ``raw_butterfly=False``. Lastly, let's
-# also refine our pattern to select only the filtered raw recording (omitting
-# the unfiltered data and the empty-room noise recordings).
-
-pattern = "sample_audvis_filt-0-40_raw.fif"
-report = mne.Report(title="parse_folder example 2", raw_psd=True, projs=True)
-report.parse_folder(
-    data_path=data_path, pattern=pattern, render_bem=False, raw_butterfly=False
-)
-report.save("report_parse_folder_raw_psd_projs.html", overwrite=True)
-
-# %%
-# This time we'll pass a specific ``subject`` and ``subjects_dir`` (even though
-# there's only one subject in the sample dataset) and remove our
-# ``render_bem=False`` parameter so we can see the MRI slices, with BEM
-# contours overlaid on top if available. Since this is computationally
-# expensive, we'll also pass the ``mri_decim`` parameter for the benefit of our
-# documentation servers, and skip processing the :file:`.fif` files.
-
-report = mne.Report(
-    title="parse_folder example 3", subject="sample", subjects_dir=subjects_dir
-)
-report.parse_folder(data_path=data_path, pattern="", mri_decim=40)
-report.save("report_parse_folder_mri_bem.html", overwrite=True)
-
-# %%
-# Now let's look at how :class:`~mne.Report` handles :class:`~mne.Evoked`
-# data (we will skip the MRIs to save computation time).
-#
-# The MNE sample dataset we're using in this example has **not** been
-# baseline-corrected; so let's apply baseline correction this now for the
-# report!
-#
-# To request baseline correction, pass a ``baseline`` argument to
-# `~mne.Report`, which should be a tuple with the starting and ending time of
-# the baseline period. For more details, see the documentation on
-# `~mne.Evoked.apply_baseline`. Here, we will apply baseline correction for a
-# baseline period from the beginning of the time interval to time point zero.
-#
-# Lastly, we want to render the "whitened" evoked data, too. Whitening
-# requires us to specify the path to a covariance matrix file via the
-# ``cov_fname`` parameter of `~mne.Report`.
-#
-# Now, let's put all of this together! Here we use a temporary directory
-# for speed so we can render a single Evoked instance, using just EEG
-# channels.
-
-baseline = (None, 0)
-cov_fname = sample_dir / "sample_audvis-cov.fif"
-pattern = "sample_audvis-ave.fif"
-evoked = mne.read_evokeds(sample_dir / pattern)[0].pick("eeg").decimate(4)
-report = mne.Report(
-    title="parse_folder example 4", baseline=baseline, cov_fname=cov_fname
-)
-with tempfile.TemporaryDirectory() as path:
-    evoked.save(Path(path) / pattern)
-    report.parse_folder(
-        path, pattern=pattern, render_bem=False, n_time_points_evokeds=5
+try:
+    report.add_bem(subject="sample", subjects_dir=subjects_dir, title="MRI & BEM")
+except Exception:
+    print("BEM unavailable.")
+
+try:
+    report.add_trans(
+        trans=trans_fname,
+        info=raw,
+        subject="sample",
+        subjects_dir=subjects_dir,
+        title="Coregistration",
+    )
+except Exception:
+    print("Coreg unavailable.")
+
+try:
+    report.add_forward(
+        forward=fwd_fname,
+        title="Forward Solution",
+        plot=True,
+        subjects_dir=subjects_dir,
+    )
+except Exception:
+    print("Forward unavailable.")
+
+try:
+    report.add_inverse_operator(
+        inverse_operator=inv_fname,
+        title="Inverse Operator",
+        plot=True,
+        subjects_dir=subjects_dir,
+    )
+except Exception:
+    print("Inverse unavailable.")
+
+"""
+This part adds source-level brain activity snapshots to the report. STCs show
+how brain signals map onto cortex over time, giving a deeper understanding of
+neural responses beyond sensor space.
+"""
+
+try:
+    stc_path = sample_dir / "sample_audvis-meg"
+    report.add_stc(
+        stc=stc_path,
+        subject="sample",
+        subjects_dir=subjects_dir,
+        title="Source Estimate",
+        n_time_points=2,
     )
-report.save("report_parse_folder_evoked.html", overwrite=True)
-
-# %%
-#
-# Adding custom HTML (e.g., a description text)
-# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-#
-# The :meth:`~mne.Report.add_html` method allows you to add custom HTML to
-# your report. This feature can be very convenient to add short descriptions,
-# lists, or reminders to your report (among many other things you can think
-# of encoding in HTML).
-
-report = mne.Report(title="Report on hypothesis 1")
-
-my_html = """
-<p>We have the following hypothesis:</p>
+except Exception:
+    print("STC unavailable.")
+
+"""
+A small HTML block is added to show that reports can include instructions,
+interpretations, or descriptive text. This is useful for documentation,
+explaining results, or guiding collaborators.
+"""
+
+html = """
+<p>Example hypothesis:</p>
 <ol>
-<li>There is a difference between images showing man-made vs. natural
-environments</li>
-<li>This difference manifests itself most strongly in the amplitude of the
-N1 ERP component</li>
+<li>Auditory vs Visual differences.</li>
+<li>Predicted N1 amplitude change.</li>
 </ol>
-<p>Below we show several plots and tests of the data.</p>
 """
+report.add_html(html, title="Hypothesis")
+
+"""
+Finally, we add an MNE logo and save the entire report as an HTML file. The
+output is fully interactive, self-contained, and easy to share, combining both
+QC and full MNE processing elements in one report.
+"""
+
+logo_path = Path(mne.__file__).parent / "icons" / "mne_icon-cropped.png"
+report.add_image(logo_path, title="MNE Logo")
 
-report.add_html(title="Hypothesis", html=my_html)
-report.save("report_add_html.html", overwrite=True)
+report.save("mne_report.html", overwrite=True)
+print("Saved as mne_report.html")

From e980448ffa9ec13772f78c3d5bfe580e990005c0 Mon Sep 17 00:00:00 2001
From: varshaa-1616 <varshaa.1616@gmail.com>
Date: Sat, 6 Dec 2025 17:34:13 +0530
Subject: [PATCH 02/10] Remove unintended files from commit

---
 doc/optipng-0.7.8-win64/OptiPNG.url     |  2 --
 doc/optipng-0.7.8-win64/doc/authors.txt | 31 -------------------------
 2 files changed, 33 deletions(-)
 delete mode 100644 doc/optipng-0.7.8-win64/OptiPNG.url
 delete mode 100644 doc/optipng-0.7.8-win64/doc/authors.txt

diff --git a/doc/optipng-0.7.8-win64/OptiPNG.url b/doc/optipng-0.7.8-win64/OptiPNG.url
deleted file mode 100644
index 9796437165b..00000000000
--- a/doc/optipng-0.7.8-win64/OptiPNG.url
+++ /dev/null
@@ -1,2 +0,0 @@
-[InternetShortcut]
-URL=http://optipng.sourceforge.net/
diff --git a/doc/optipng-0.7.8-win64/doc/authors.txt b/doc/optipng-0.7.8-win64/doc/authors.txt
deleted file mode 100644
index 0245e5ab1be..00000000000
--- a/doc/optipng-0.7.8-win64/doc/authors.txt
+++ /dev/null
@@ -1,31 +0,0 @@
-# OptiPNG version 0.7.8
-# Copyright (C) 2001-2023 Cosmin Truta and the Contributing Authors.
-# See the accompanying LICENSE file for details.
-#
-# A Contributing Author is a person or company who contributed code that
-# is now part of OptiPNG.
-#
-# For the purpose of copyright and licensing, this is the official list
-# of Contributing Authors, in alphabetic order.
-
-Adam Ciarcinski
-Brian McQuade
-Elias Pipping
-Fabien Barbier
-Friedrich Preuss
-Maciej Pilichowski
-Matthew Fearnley
-Nelson A. de Oliveira
-Niels de Koning
-Oliver Schneider
-Petr Gajdos
-Piotr Bandurski
-Priit Laes
-Ramona C. Truta
-Sebastian Pipping
-Stefan Br�ns
-Thomas Hurst
-Till Maas
-Ville Skytt�
-Vincent Lef�vre
-Yuen Ho Wong

From 7657bb8a85a63336966e707e49611f6884db9bc9 Mon Sep 17 00:00:00 2001
From: varshaa-1616 <varshaa.1616@gmail.com>
Date: Tue, 16 Dec 2025 13:45:17 +0530
Subject: [PATCH 03/10] Remove unintended generated and unrelated files

---
 doc/optipng-0.7.8-win64/doc/history.txt     | 435 --------------------
 doc/optipng-0.7.8-win64/doc/license.txt     |  21 -
 doc/optipng-0.7.8-win64/doc/optipng.man.pdf | Bin 42393 -> 0 bytes
 doc/optipng-0.7.8-win64/doc/optipng.man.txt | 299 --------------
 doc/optipng-0.7.8-win64/doc/todo.txt        |  42 --
 doc/optipng-0.7.8-win64/optipng.exe         | Bin 229888 -> 0 bytes
 6 files changed, 797 deletions(-)
 delete mode 100644 doc/optipng-0.7.8-win64/doc/history.txt
 delete mode 100644 doc/optipng-0.7.8-win64/doc/license.txt
 delete mode 100644 doc/optipng-0.7.8-win64/doc/optipng.man.pdf
 delete mode 100644 doc/optipng-0.7.8-win64/doc/optipng.man.txt
 delete mode 100644 doc/optipng-0.7.8-win64/doc/todo.txt
 delete mode 100644 doc/optipng-0.7.8-win64/optipng.exe

diff --git a/doc/optipng-0.7.8-win64/doc/history.txt b/doc/optipng-0.7.8-win64/doc/history.txt
deleted file mode 100644
index ccd3746dc2e..00000000000
--- a/doc/optipng-0.7.8-win64/doc/history.txt
+++ /dev/null
@@ -1,435 +0,0 @@
-OptiPNG - Revision history
-==========================
-
-Legend
-------
-++ Added or improved performance-related feature
-   (might improve compression ratio or processing speed).
- + Added or improved feature.
- - Removed feature.
- ! Fixed bug.
-!! Fixed critical bug
-   (crash, data/metadata loss or security hazard).
- * Other modification (e.g. architectural improvement).
-
-Version 0.7.8   2023-nov-03
--------------
- * Upgraded libpng to version 1.6.40.
- * Upgraded zlib to version 1.3-optipng.
- * Upgraded cexcept to version 2.0.2-optipng.
-!! Fixed a global-buffer-overflow vulnerability in the GIF reader.
-   [Reported by Zeng Yunxiang; fixed by Thomas Hurst]
- ! Fixed a stack-print-after-scope defect in the error handler.
- ! Fixed an assertion failure in the image reduction module.
- ! Fixed the command-line wildargs expansion in the Windows port.
- * Raised the minimum required libpng version from 1.2.9 to 1.6.35.
- * Raised the minimum required zlib version from 1.2.1 to 1.2.8.
- * Refactored the structured exception handling.
-
-Version 0.7.7   2017-dec-27
--------------
- * Upgraded libpng to version 1.6.34.
- * Upgraded zlib to version 1.2.11-optipng.
- * Upgraded minitiff to version 0.2.
-!! Fixed a buffer overflow vulnerability in the GIF decoder.
-   [Reported by Joonun Jang]
-!! Fixed an integer overflow vulnerability in the TIFF decoder.
-   [Reported by Jaeseung Choi]
- ! Fixed the build on macOS High Sierra.
-   [Reported by various users]
-   [Fixed by Yuen Ho Wong and Friedrich Preuss]
- ! Fixed the build on DJGPP.
- * Disallowed out-of-bounds values in rangeset options.
-
-Version 0.7.6   2016-apr-03   [Released by Ramona C. Truta]
--------------
- * Upgraded libpng to version 1.6.21.
- ! Fixed an assertion failure in the image reduction code.
-   [Fixed by upgrading libpng]
-!! Fixed various security-sensitive defects in the BMP decoder.
-   [Reported by Henri Salo and Hans Jerry Illikainen]
-   [Fixed by Ramona C. Truta]
- ! Fixed a benign uninitialized memory read in the GIF decoder.
-   [Reported by Gustavo Grieco]
- ! Fixed a build failure occurring under the Estonian (et_EE) locale.
-   [Reported by Sebastian Pipping]
-   [Fixed by Priit Laes]
- ! Fixed a build failure occurring on Mac OS X, FreeBSD, and possibly
-   other systems that lack POSIX-compliant high-resolution timestamps.
-   [Reported by Ryan Schmidt and Dmitry Egorov]
-   [Contributed by Sebastian Pipping]
- ! Fixed a typo causing build failures in 32-bit ANSI C compilation.
-   [Reported by various users]
-
-Version 0.7.5   2014-mar-24
--------------
- * Upgraded libpng to version 1.6.10-optipng.
- * Upgraded zlib to version 1.2.8-optipng.
- ! Fixed various build issues with libpng-1.5 and libpng-1.6.
-   [Fixed by Oliver Schneider]
- * Allowed the handling of huge image files (> millions of pixels
-   per row or column) to be independent of the libpng version.
- + Allowed the option -preserve to save the file ownership (UID/GID)
-   on Unix.
-   [Requested by Otto Kek�l�inen]
- ! Fixed a build issue with Clang.
- + Added various enhancements to the configure script.
-
-Version 0.7.4   2012-oct-21
--------------
-!! Fixed the previous fix, which failed to fix the option -fix.
-   [Reported by Gynvael Coldwind and Mateusz Jurczyk]
-
-Version 0.7.3   2012-sep-16
--------------
-!! Fixed a use-after-free vulnerability in the palette reduction code.
-   This vulnerability was accidentally introduced in version 0.7.
-
-Version 0.7.2   2012-aug-24
--------------
- * Upgraded libpng to version 1.4.12.
- * Upgraded zlib to version 1.2.7-optipng.
- ! Fixed the display of huge (4GB+) file/IDAT sizes on 32-bit platforms.
- ! Issued a proper error message if the output IDAT can't fit in 2GB.
-   Acknowledged this limitation in the user manual.
-   [Reported by John Sauter]
- ! Fixed the output file cleanup that should occur after a write error.
- * Added the option -debug and various undocumented debug features.
- * Moved the PNG reduction module (opngreduc) to a separate sub-project.
-
-Version 0.7.1   2012-mar-19   [Released by Ramona C. Truta]
--------------
-!! Fixed a regression in the reduction of palette-encoded grayscale
-   images. (This regression was introduced in version 0.7.)
-   [Fixed by Adam Ciarcinski]
-
-Version 0.7     2012-feb-29   [Released by Cosmin & Ramona C. Truta]
------------
- * Upgraded libpng to version 1.4.9.
- * Upgraded zlib to version 1.2.6-optipng.
-!! Fixed a rarely-occurring out-of-bounds memory access error in
-   the Z_RLE strategy in zlib.
-   [Reported by Christopher Wichura]
-   [Fixed by upgrading zlib]
- + Added the popularly-requested option -strip.
-   The only suboption currently supported is "-strip all".
- + Added the option -clobber.
-   [Contributed by Maciej Pilichowski]
- + Added the option -backup, as an alias of -keep.
-   [Contributed by Ramona C. Truta]
- + Added the option -silent, as an alias of -quiet.
-   [Contributed by Ramona C. Truta]
- - Deprecated the option -log.
-   [Contributed by Ramona C. Truta]
- * Changed the activity display output from STDOUT to STDERR.
- + Allowed the option -preserve to save high-resolution timestamps
-   on Unix, if the POSIX-1.2008 API is available.
-   (This feature was previously available on Windows only.)
- ! Fixed a minor precision error in the display of file size percents.
- ! Fixed a memory leak that occurred when reading broken GIF images.
- ! Fixed various build issues.
-   [Fixed by Sebastian Pipping and Ville Skytt�]
- * Resolved all remaining compatibility issues with libpng-1.5.
-   [Contributed by Adam Ciarcinski]
- * Added build support for clang.
- * Reorganized the source directory structure.
-
-Version 0.6.5   2011-jan-24
--------------
- * Upgraded libpng to version 1.4.5-optipng.
- * Upgraded zlib to version 1.2.5-optipng.
-!! Fixed the I/O states (in libpng 1.4.5);
-   they caused incorrect file reads in some rare cases.
-   [Reported by Dmitry Marakasov]
-!! Fixed processing of PNG files with chunks of size 0.
-   [Reported by Matthew Fearnley]
- ! Fixed a display error in the TIFF import.
-   [Fixed by Piotr Bandurski]
- + Improved checking of the arguments of -f, -zc, -zm and -zs.
- - Removed quirks from the rangeset option argument syntax.
- ! Fixed a build issue under the system-supplied libpng-1.4.
-   [Fixed by Petr Gajdos]
- * Resolved forward-compatibility issues regarding libpng-1.5;
-   however, the system-supplied libpng-1.5 is not yet supported.
- * Added various enhancements to the configure+make build system.
-   [Contributed by Elias Pipping and Dmitri Zubko]
-
-Version 0.6.4   2010-mar-14
--------------
- * Upgraded libpng to version 1.4.1-optipng.
- * Upgraded zlib to version 1.2.4-optipng.
- + Added the option -nx.
- * Clarified the behavior of the option -nz and the relationship between
-   the options -nz and -o0.
- + Added a filesystem check (resolving normalized paths, symlinks, etc.)
-   to better detect when the output overwrites the input.
- + Enabled automatic wildcard expansion (i.e. globbing) on Win64.
- ! Fixed a Unicode build issue on Windows.
-   [Fixed by Fabien Barbier]
-
-Version 0.6.3   2009-may-18
--------------
- * Upgraded libpng to version 1.2.36-optipng.
-!! Fixed a use-after-free error in the GIF reader.
-   [Reported by Roy Tam]
-   [Fixed by Bryan McQuade]
- ! Flushed the output log to display the current trial in real time.
-   This only worked on Windows in the previous version.
-   [Fixed by Vincent Lef�vre]
- ! Fixed an error in reporting unrecognized file formats.
- - Removed the requirement to "fix" TIFF files that contain unrecognized
-   metadata.
-   [Requested by Piotr Bandurski]
- * Simplified the option abbreviation rules. Option names can now be
-   abbreviated to their shortest unique prefix, as in X11 applications.
-
-Version 0.6.2   2008-nov-09
--------------
- * Upgraded libpng to version 1.2.33-optipng.
-++ Put back a speed optimization, accidentally removed in version 0.6,
-   allowing singleton trials (-o1) to be bypassed in certain conditions.
-!! Fixed an array overflow in the BMP reader.
-!! Fixed the loss of private chunks under the option -snip.
- + Produced a more concise on-screen output in the non-verbose mode.
-   [Contributed by Vincent Lef�vre]
- * Added a programming interface to the optimization engine, in order
-   to facilitate the development of PNG-optimizing GUI apps and plugins.
-
-Version 0.6.1   2008-jul-20
--------------
- * Upgraded cexcept to version 2.0.1.
- + Added a configure script, to be used instead of unix-secure.mak.
- ! Fixed a build issue that occurred when using libpng from the system.
-   [Reported by Nelson A. de Oliveira]
- ! Fixed the processing when the image reduction yields an output larger
-   than the original.
-   [Reported by Michael Krishtopa]
- ! Fixed the behavior of the option -preserve.
-   [Reported by Bill Koch]
- - Removed displaying of partial progress when abandoning IDATs under
-   the option -v. (The percentages displayed were not very accurate.)
-
-Version 0.6     2008-jun-15
------------
- * Upgraded libpng to version 1.2.29-optipng.
-++ Implemented grayscale(alpha)-to-palette reductions.
-++ Improved conversion of bKGD info during RGB-to-palette reductions.
-   [Contributed by Matthew Fearnley]
-!! Fixed conversion of bKGD and tRNS during 16-to-8-bit reductions.
-   [Reported by Matthew Fearnley]
- + Added support for compressed BMP (incl. PNG-compressed BMP, you bet!)
- + Improved the speed of reading raw PNM files.
- + Recognized PNG digital signatures (dSIG) and disabled optimization
-   in their presence, to preserve their integrity.
- + Allowed the user to enforce the optimization of dSIG'ed files.
- + Recognized APNG animation files and disabled reductions to preserve
-   their integrity.
- + Added the option -snip, to allow the user to snip one image out of
-   a multi-image file, such as animated GIF, multi-page TIFF, or APNG.
- + Improved recovery of PNG files with incomplete IDAT.
-!! Fixed a crash triggered by the use of -log on some platforms.
-   [Fixed by Stefan Br�ns]
- ! Fixed the behavior of the options -out and -dir when the input is
-   already optimized.
-   [Reported by Christian Davideck]
- * Provided more detailed image information at the start of processing.
- * Provided a more detailed summary at the end of processing, under the
-   presence of the option -v and/or the occurrence of exceptional events.
-
-Version 0.5.5   2007-jan-28
--------------
- * Upgraded libpng to version 1.2.15-optipng.
-++ Used a previously-missed RGB-to-palette reduction opportunity
-   for images containing 256 distinct colors.
-   [Reported by Joachim Kluge]
-!! Fixed conversion of bKGD info during RGB-to-palette reductions.
-   [Reported by Matthew Fearnley]
- ! Fixed pre-computation of iterations.
-   [Reported by Matthew Fearnley]
- ! Eliminated a false alarm when processing RGB images with tRNS
-   in Unix-secure mode.
-   [Reported by Till Maas]
-   [Fixed by Nelson A. de Oliveira]
- ! Fixed the behavior of the options -out and -dir when changing
-   interlacing.
-   [Reported by Martin Packman]
- ! Fixed the behavior of "-dir [DRIVE]:" on Windows.
-
-Version 0.5.4   2006-aug-11
--------------
- + Added the options -out and -dir, to specify the name of the
-   output file or directory.
-   [Requested by Alexander Lucas]
- * Added support for builds based on the system-supplied libpng.
-   [Contributed by Nelson A. de Oliveira]
-
-Version 0.5.3   2006-jul-23
--------------
- * Upgraded libpng to version 1.2.12-optipng.
- + Implemented basic support for TIFF (grayscale, RGB and RGBA,
-   uncompressed).
-++ Avoided the redundant trial when the search space is singular
-   (e.g. when running "optipng -o1 example.tif").
- + Prevented accidental file corruption when using the option -log.
- ! Fixed (again) a small typo in the online help.
-
-Version 0.5.2   2006-may-07
--------------
- + Improved handling of inexact PNM-to-PNG conversions.
- ! Fixed a typo that was breaking the build on some Unix platforms.
-   [Reported by Aaron Reitz]
-
-Version 0.5.1   2006-apr-30
--------------
-++ Implemented bit depth reduction for palette images.
- * Upgraded libpng to version 1.2.10-optipng.
- + Improved the BMP support.
- + Added a Unix man page.
-   [Contributed by Nelson A. de Oliveira]
- + Allowed abbreviation of command-line options.
- + Changed the option -log to accept a file name as an argument.
- * Renamed the option -no to -simulate.
- ! Fixed an error in handling .bak files on Unix.
-   [Reported by Adam Szojda and Nelson A. de Oliveira]
- ! Fixed a small typo in the help screen.
-   [Reported by A. Costa and Nelson A. de Oliveira]
-
-Version 0.5     2006-jan-14
------------
-++ Added pngxtern, a libpng add-on for external image format
-   support: BMP (uncompressed), GIF, PNM.
-++ Implemented RGB(A)-to-palette reductions.
- * Upgraded zlib to version 1.2.3-optipng.
- * Upgraded libpng to version 1.2.8-optipng.
- + If trials are ended prematurely, detailed progression is only
-   reported under the option -v.
- - Removed reporting of some IDAT sizes that exceeded the optimum.
-   (This was NOT a bug, but a "feature" that confused some users.)
- ! Fixed an RGB-to-gray reduction problem that occurred under some
-   specific background colors.
- * Added support for builds based on the system-supplied zlib.
-   [Requested by Nelson A. de Oliveira]
- * Modified LICENSE. It is now a verbatim spell of the zlib license.
-
-Version 0.4.8   2005-may-10
--------------
- * Upgraded libpng to version 1.0.18-optipng.
-!! Fixed a palette-to-gray reduction problem that occurred when an
-   RGB triple had both an alpha below max, and an alpha equal to max.
-   [Reported by Nicolas Le Gland]
- + Packed the Windows executable using UPX.
-
-Version 0.4.7   2004-oct-30
--------------
-!! Fixed a palette-to-gray reduction problem that occurred when
-   having more than one alpha value per RGB triple.
-   [Reported by Larry Hastings]
- ! Fixed the progress display, when processing very large images.
- + Displayed the image info at the beginning of processing.
-++ Reduced the IDAT buffer size, allowing abandoned trials to
-   terminate earlier in some circumstances.
- + Implemented error recovery, when PLTE is too small, and/or
-   tRNS is too large.
-
-Version 0.4.6   2004-oct-25
--------------
- * Upgraded zlib to version 1.2.2-optipng.
- * Upgraded libpng to version 1.0.17-optipng.
-   This provides safe handling of some ill-formed PNG images.
- + Rewrote makefiles.
- + Added project workspace to build under Visual C++ 6.0,
-   integrated with memory leak detection.
-++ Implemented a premature termination of trials, in the moment
-   when IDAT grows beyond the smallest size previously achieved.
-   [Requested by Larry Hastings]
- + Changed the order of trials, to perform the trials that are
-   more likely to yield a smaller IDAT, at the beginning.
- + Added the option -full to avoid the premature termination of
-   trials; useful for debugging.
-
-Version 0.4.5   2004-may-31
--------------
- * Upgraded zlib to version 1.2.1.f-cos2.
- * Upgraded libpng to version 1.0.15-cos2.
- * Renamed the option -nx to -nz.
- + Added the option -preserve to preserve file attributes
-   (file mode, time stamp, etc.) where applicable.
-   [Requested by Nehal Mistry]
- ! Fixed an incorrect initialization of zlib window bits.
- ! Displayed an error message when the search space was invalid.
-!! Fixed a palette reduction problem for bit depths below 8.
- ! Eliminated memory leaks.
-   [Contributed by Niels de Koning]
-
-Version 0.4.4   2003-nov-20
--------------
- * Upgraded zlib to version 1.2.1.
-++ Added support for the Z_RLE strategy.
-
-Version 0.4.3   2003-aug-12
--------------
- ! Fixed a reduction problem that caused an assertion failure.
-   [Reported by Dimitri Papadopoulos]
-
-Version 0.4.2   2003-jun-30
--------------
-++ Enhanced the support for palette size reductions:
-   trailing sterile palette entries are removed even when
-   the bit depth is below 8.
- ! Enforced recompression when the new IDAT has the same size,
-   but other chunks have been reduced.
- + Displayed the IDAT size difference as a percentage.
-   [Requested by Nehal Mistry]
-
-Version 0.4.1   2003-may-19
--------------
- ! Fixed the removal of trailing sterile palette entries.
-
-Version 0.4     2003-may-12
------------
-++ Added support for palette-to-gray reductions.
-++ Added partial support for palette size reductions.
- ! Fixed the reporting of invalid command-line options.
- ! Eliminated a spurious warning when the zlib window size
-   is set to 256.
-
-Version 0.3.2   2003-mar-11
--------------
- + Added support for updating sBIT during reductions.
- ! Fixed the reduction of the alpha channel.
-
-Version 0.3.1   2003-feb-25
--------------
- ! Fixed the encoding of interlaced images when they become
-   larger than the input.
-   [Reported by James H. Cloos, Jr.]
- + Added the HISTORY document (this file).
-
-Version 0.3     2003-feb-24
------------
- * Announced the first public release of OptiPNG.
-++ Added support for iterating through zlib memory levels.
-++ Added support for collapsing IDAT, avoiding calls to
-   png_set_compression_buffer_size().
-   This reduces the memory requirements.
-++ Added support for lossless reduction of the image type:
-   RGB[A] -> G[A], RGBA -> RGB, GA -> G
- + Added many user options.
- + Added documentation.
-
-Version 0.2     2001-dec-27
------------
- + Added support for optimization level presets.
- + Added a user option for changing the interlacing.
-
-Version 0.1     2001-dec-17
------------
- + Added support for chunk I/O status annotation.
-   This improves the speed of OptiPNG significantly.
- * Added structured exception handling via cexcept.
-
-Version 0.0.1   2001-dec-10
--------------
- * Introduced OptiPNG.
-++ Compressed PNG IDAT data repeatedly, iterating through zlib
-   compression and strategy levels, as well as PNG delta filters.
diff --git a/doc/optipng-0.7.8-win64/doc/license.txt b/doc/optipng-0.7.8-win64/doc/license.txt
deleted file mode 100644
index 58fbad30883..00000000000
--- a/doc/optipng-0.7.8-win64/doc/license.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-Copyright (C) 2001-2023 Cosmin Truta and the Contributing Authors.
-For the purpose of copyright and licensing, the list of Contributing
-Authors is available in the accompanying AUTHORS file.
-
-This software is provided 'as-is', without any express or implied
-warranty.  In no event will the author(s) be held liable for any damages
-arising from the use of this software.
-
-Permission is granted to anyone to use this software for any purpose,
-including commercial applications, and to alter it and redistribute it
-freely, subject to the following restrictions:
-
-1. The origin of this software must not be misrepresented; you must not
-   claim that you wrote the original software.  If you use this software
-   in a product, an acknowledgment in the product documentation would be
-   appreciated but is not required.
-
-2. Altered source versions must be plainly marked as such, and must not
-   be misrepresented as being the original software.
-
-3. This notice may not be removed or altered from any source distribution.
diff --git a/doc/optipng-0.7.8-win64/doc/optipng.man.pdf b/doc/optipng-0.7.8-win64/doc/optipng.man.pdf
deleted file mode 100644
index 4f8b7083bf4c48e3a60fb7a118bbf5825f78889b..0000000000000000000000000000000000000000
GIT binary patch
diff --git a/doc/optipng-0.7.8-win64/doc/optipng.man.txt b/doc/optipng-0.7.8-win64/doc/optipng.man.txt
deleted file mode 100644
index f2b1a458ea6..00000000000
--- a/doc/optipng-0.7.8-win64/doc/optipng.man.txt
+++ /dev/null
@@ -1,299 +0,0 @@
-OPTIPNG(1)                  General Commands Manual                 OPTIPNG(1)
-
-NAME
-       OptiPNG - Optimize Portable Network Graphics files
-
-SYNOPSIS
-       optipng [-? | -h | -help]
-       optipng [options...] files...
-
-DESCRIPTION
-       The  OptiPNG  program  shall attempt to optimize PNG files, i.e. reduce
-       their size to a minimum, without losing semantic information. In  addi-
-       tion,  this  program  shall perform a suite of auxiliary functions like
-       integrity checks, metadata recovery and pixmap-to-PNG conversion.
-
-       The optimization attempts are not  guaranteed  to  succeed.  Valid  PNG
-       files  that  cannot  be optimized by this program are normally left in-
-       tact; their size will not grow. The user may request to  override  this
-       default behavior.
-
-FILES
-       The  input  files  are  raster image files encoded either in PNG format
-       (the native format), or in an external format. The currently  supported
-       external formats are GIF, BMP, PNM and TIFF.
-
-       OptiPNG processes each image file given in the command line as follows:
-
-       - If the image is in PNG format:
-
-              Attempts to optimize the given file in-place. If optimization is
-              successful,  or  if  the  option -force is enabled, replaces the
-              original file with its optimized version. The original  file  is
-              backed up if the option -keep is enabled.
-
-       - If the image is in an external format:
-
-              Creates  an  optimized PNG version of the given file. The output
-              file name is composed from the original file name and  the  .png
-              extension.
-
-       Existing  files  are not overwritten, unless the option -clobber is en-
-       abled.
-
-OPTIONS
-   General options
-       -?, -h, -help
-              Show a complete summary of options.
-
-       -backup, -keep
-              Keep a backup of the modified files.
-
-       -clobber
-              Overwrite the existing output and backup files.
-              Under this option, if the option -backup is not enabled, the old
-              backups of the overwritten files are deleted.
-
-       -dir directory
-              Write the output files to directory.
-
-       -fix   Enable error recovery. This option has no effect on valid  input
-              files.
-              The  program will spend a reasonable amount of effort to recover
-              as much data as possible, without  increasing  the  output  file
-              size,  but  the success cannot be generally guaranteed. The pro-
-              gram may even increase the file size,  e.g.,  by  reconstructing
-              missing  critical  data. Under this option, integrity shall take
-              precedence over file size.
-              When this option is not used, the invalid input files  are  left
-              unprocessed.
-
-       -force Enforce writing of a new output file.
-              This  option  overrides the program's decision not to write such
-              file, e.g. when the PNG input is digitally signed (using  dSIG),
-              or when the PNG output becomes larger than the PNG input.
-
-       -log file
-              Log  messages  to  file.  For safety reasons, file must have the
-              extension .log.
-              This option is deprecated and will be  removed  eventually.  Use
-              shell redirection.
-
-       -out file
-              Write  output  file  to file.  The command line must contain ex-
-              actly one input file.
-
-       -preserve
-              Preserve file attributes (time stamps, file access rights, etc.)
-              where applicable.
-
-       -quiet, -silent
-              Run in quiet mode.
-              The messages are still written to the log  file  if  the  option
-              -log is enabled.
-
-       -simulate
-              Run  in  simulation  mode: perform the trials, but do not create
-              output files.
-
-       -v     Enable the options -verbose and -version.
-
-       -verbose
-              Run in verbose mode.
-
-       -version
-              Show copyright, version and build info.
-
-       --     Stop option switch parsing.
-
-   PNG encoding and optimization options
-       -o level
-              Select the optimization level.
-              The optimization level 0 enables a set  of  optimization  opera-
-              tions  that  require minimal effort. There will be no changes to
-              image attributes like bit depth or color type, and no recompres-
-              sion of existing IDAT datastreams.
-              The optimization level  1  enables  a  single  IDAT  compression
-              trial. The trial chosen is what OptiPNG thinks it's probably the
-              most effective.
-              The  optimization  levels 2 and higher enable multiple IDAT com-
-              pression trials; the higher the level, the more trials.
-              The behavior and the default value of  this  option  may  change
-              across  different program versions. Use the option -h to see the
-              details pertaining to your specific version.
-
-       -f filters
-              Select the PNG delta filters.
-              The filters argument is specified as a  rangeset  (e.g.  -f0-5),
-              and  the default filters value depends on the optimization level
-              set by the option -o.
-              The filter values 0, 1, 2, 3 and 4  indicate  static  filtering,
-              and correspond to the standard PNG filter codes (None, Left, Up,
-              Average  and  Paeth, respectively). The filter value 5 indicates
-              adaptive filtering, whose effect is defined by the libpng(3) li-
-              brary used by OptiPNG.
-
-       -full  Produce a full report on IDAT.  This option might slow down  the
-              trials.
-
-       -i type
-              Select the interlace type (0-1).
-              If  the  interlace type 0 is selected, the output image shall be
-              non-interlaced (i.e. progressive-scanned). If the interlace type
-              1 is selected, the output image shall be  interlaced  using  the
-              Adam7 method.
-              By default, the output shall have the same interlace type as the
-              input.
-
-       -nb    Do not apply bit depth reduction.
-
-       -nc    Do not apply color type reduction.
-
-       -np    Do not apply palette reduction.
-
-       -nx    Do  not  apply  any lossless image reduction: enable the options
-              -nb, -nc and -np.
-
-       -nz    Do not recode IDAT datastreams.
-              The IDAT optimization operations that do  not  require  recoding
-              (e.g. IDAT chunk concatenation) are still performed.
-              This option has effect on PNG input files only.
-
-       -zc levels
-              Select the zlib compression levels used in IDAT compression.
-              The  levels  argument  is specified as a rangeset (e.g. -zc6-9),
-              and the default levels value depends on the  optimization  level
-              set by the option -o.
-              The effect of this option is defined by the zlib(3) library used
-              by OptiPNG.
-
-       -zm levels
-              Select the zlib memory levels used in IDAT compression.
-              The  levels  argument  is specified as a rangeset (e.g. -zm8-9),
-              and the default levels value depends on the  optimization  level
-              set by the option -o.
-              The effect of this option is defined by the zlib(3) library used
-              by OptiPNG.
-
-       -zs strategies
-              Select the zlib compression strategies used in IDAT compression.
-              The  strategies  argument  is  specified  as  a  rangeset  (e.g.
-              -zs0-3), and the default strategies value depends on  the  opti-
-              mization level set by the option -o.
-              The effect of this option is defined by the zlib(3) library used
-              by OptiPNG.
-
-       -zw size
-              Select  the  zlib window size (32k,16k,8k,4k,2k,1k,512,256) used
-              in IDAT compression.
-              The size argument can be specified either in bytes (e.g.  16384)
-              or  kilobytes  (e.g.  16k). The default size value is set to the
-              lowest window size that yields an  IDAT  output  as  big  as  if
-              yielded by the value 32768.
-              The effect of this option is defined by the zlib(3) library used
-              by OptiPNG.
-
-   Editing options
-       -snip  Cut one image out of multi-image, animation or video files.
-              Depending  on  the input format, this may be either the first or
-              the most relevant (e.g. the largest) image.
-
-       -strip objects
-              Strip metadata objects from a PNG file.
-              PNG metadata is the information stored in  any  ancillary  chunk
-              except tRNS.  (tRNS represents the alpha channel, which, even if
-              ignored  in  rendering,  is  still a proper image channel in the
-              RGBA color space.)
-              The only option currently supported is -strip all.
-
-   Notes
-       Options may come in any order (except for --), before, after, or alter-
-       nating with file names. Option names are case-insensitive  and  may  be
-       abbreviated to their shortest unique prefix.
-
-       Some  options may have arguments that follow the option name, separated
-       by whitespace or the equal sign ('='). If the option argument is a num-
-       ber or a rangeset, the separator may be omitted. For example:
-
-              -out newfile.png  <=>  -out=newfile.png
-              -o3  <=>  -o 3  <=>  -o=3
-              -f0,3-5  <=>  -f 0,3-5  <=>  -f=0,3-5
-
-       Rangeset arguments are cumulative; e.g.
-
-              -f0 -f3-5  <=>  -f0,3-5
-              -zs0 -zs1 -zs2-3  <=>  -zs0,1,2,3  <=>  -zs0-3
-
-EXTENDED DESCRIPTION
-       The PNG optimization algorithm consists of the following steps:
-
-       1.  Reduce the bit depth, the color type and the color palette  of  the
-           image.   This  step  may reduce the size of the uncompressed image,
-           which, indirectly, may reduce the  size  of  the  compressed  image
-           (i.e. the size of the output PNG file).
-
-       2.  Run  a  suite  of compression methods and strategies and select the
-           compression parameters that yield the smallest output file.
-
-       3.  Store all IDAT contents into a single chunk, eliminating the  over-
-           head incurred by repeated IDAT headers and CRCs.
-
-       4.  Set the zlib window size inside IDAT to a mininum that does not af-
-           fect the compression ratio, reducing the memory requirements of PNG
-           decoders.
-
-       Not all of the above steps need to be executed. The behavior depends on
-       the actual input files and user options.
-
-       Step  1  may  be customized via the no-reduce options -nb, -nc, -np and
-       -nx. Step 2 may be customized via the -o option, and may be  fine-tuned
-       via  the options -zc, -zm, -zs and -zw. Step 3 is always executed. Step
-       4 is executed only if a new IDAT is being created,  and  may  be  fine-
-       tuned via the option -zw.
-
-       Extremely  exhaustive searches are not generally expected to yield sig-
-       nificant improvements in compression ratio, and are recommended to  ad-
-       vanced users only.
-
-EXAMPLES
-       optipng file.png      # default speed
-       optipng -o5 file.png  # slow
-       optipng -o7 file.png  # very slow
-
-BUGS
-       Lossless  image  reductions are not completely implemented.  (This does
-       not affect the integrity of the output files.)  Here  are  the  missing
-       pieces:
-
-              - The color palette reductions are implemented only partially.
-              -  The  bit  depth reductions below 8, for grayscale images, are
-              not implemented yet.
-
-       Encoding of images whose total IDAT size exceeds 2GB is not supported.
-
-       TIFF support is limited to uncompressed, PNG-compatible (grayscale, RGB
-       and RGBA) images.
-
-       Metadata is not imported from the external image formats.
-
-       There is no support for pipes, streams, extended file attributes or ac-
-       cess control lists.
-
-SEE ALSO
-       png(5), libpng(3), zlib(3), pngcrush(1), pngrewrite(1).
-
-STANDARDS
-       The files produced by OptiPNG are compliant with PNG-2003:
-       Glenn Randers-Pehrson et al.  Portable Network Graphics (PNG)  Specifi-
-       cation, Second Edition.
-       W3C Recommendation 10 November 2003; ISO/IEC IS 15948:2003 (E).
-       http://www.w3.org/TR/PNG/
-
-AUTHOR
-       OptiPNG is written and maintained by Cosmin Truta.
-
-       This  manual  page  was originally written by Nelson A. de Oliveira for
-       the Debian Project. It was later updated by Cosmin Truta,  and  is  now
-       part of the OptiPNG distribution.
-
-OptiPNG version 0.7.8             2023-Nov-03                       OPTIPNG(1)
diff --git a/doc/optipng-0.7.8-win64/doc/todo.txt b/doc/optipng-0.7.8-win64/doc/todo.txt
deleted file mode 100644
index f4a6c1b80aa..00000000000
--- a/doc/optipng-0.7.8-win64/doc/todo.txt
+++ /dev/null
@@ -1,42 +0,0 @@
-OptiPNG - TO-DO list
-====================
-
-- Compression improvements:
-  Use zlib's deflateTune().
-  Use 7zip's and/or zopfli's powerful deflation engine.
-
-- Speed improvements:
-  Avoid repeated filtering when trying a filter value more than once.
-
-- Text chunk optimization:
-  Smart selection between tEXt and zTXt.
-  Smart selection between uncompressed iTXt and compressed iTXt.
-
-- Improved support for reading external image formats
-  (e.g. compressed TIFF).
-
-- More file recovery features.
-
-- Input from stdin; output to stdout:
-    cat infile | optipng > outfile
-    optipng -stdout infile > outfile
-
-- Optimization of an entire directory, with and without subdirectory
-  recursion:
-    optipng dir/
-    optipng -recursive dir/
-
-- Support for conversion to a desired bit depth and color type:
-    optipng -b16 -c6 files ...
-
-- Support for handling metadata, e.g.:
-    optipng -set tEXt=<keyword>,<text>     # add or update chunk
-    optipng -set sRGB=0                    # add or update chunk
-    optipng -set image.precision=<n>       # set the precision of all samples
-    optipng -set image.alpha.precision=<n> # set the precision of alpha samples
-    optipng -reset image.alpha             # make the image fully opaque
-    optipng -strip hIST,sPLT               # strip hIST and sPLT
-    optipng -strip all -protect iCCP       # strip all metadata except iCCP
-
-- Parallelization on multi-processor/multi-core machines:
-    optipng -jobs 4 files ...
diff --git a/doc/optipng-0.7.8-win64/optipng.exe b/doc/optipng-0.7.8-win64/optipng.exe
deleted file mode 100644
index 76920bad2dc1340a9e1dad6a34d64f29fda7f183..0000000000000000000000000000000000000000
GIT binary patch

From a58b2db54cba5ada70aac57ac0aa887a1f9e56c5 Mon Sep 17 00:00:00 2001
From: varshaa-1616 <varshaa.1616@gmail.com>
Date: Tue, 16 Dec 2025 13:46:07 +0530
Subject: [PATCH 04/10] Revert changes to existing report tutorial

---
 tutorials/intro/70_report.py | 880 ++++++++++++++++++++++++++---------
 1 file changed, 656 insertions(+), 224 deletions(-)

diff --git a/tutorials/intro/70_report.py b/tutorials/intro/70_report.py
index b44d44f09f8..7fe30ff6b96 100644
--- a/tutorials/intro/70_report.py
+++ b/tutorials/intro/70_report.py
@@ -6,266 +6,698 @@
 ===============================
 
 :class:`mne.Report` is a way to create interactive HTML summaries of your data.
-These reports can show many different visualizations for one or multiple
-participants. A common use case is creating diagnostic summaries to check data
-quality at different stages in the processing pipeline. The report can show
-things like plots of data before and after each preprocessing step, epoch
-rejection statistics, MRI slices with overlaid BEM shells, all the way up to
-plots of estimated cortical activity.
-
-Compared to a Jupyter notebook, :class:`mne.Report` is easier to deploy, as the
-HTML pages it generates are self-contained and do not require a running Python
-environment. However, it is less flexible as you can't change code and re-run
-something directly within the browser. This tutorial covers the basics of
-building a report.
-
-This tutorial demonstrates how to generate a full MNE-Python report combining:
-- Quality Control (QC) steps: raw data, PSD, events, epochs, ICA
-- Full MNE diagnostics: covariance, projectors, BEM, coregistration,
-  forward/inverse solutions, source estimates
-- Custom figures and HTML content
+These reports can show many different visualizations for one or multiple participants.
+A common use case is creating diagnostic summaries to check data quality at different
+stages in the processing pipeline. The report can show things like plots of data before
+and after each preprocessing step, epoch rejection statistics, MRI slices with overlaid
+BEM shells, all the way up to plots of estimated cortical activity.
+
+Compared to a Jupyter notebook, :class:`mne.Report` is easier to deploy, as the HTML
+pages it generates are self-contained and do not require a running Python environment.
+However, it is less flexible as you can't change code and re-run something directly
+within the browser. This tutorial covers the basics of building a report. As usual,
+we will start by importing the modules and data we need:
 """
 
 # Authors: The MNE-Python contributors.
 # License: BSD-3-Clause
 # Copyright the MNE-Python contributors.
 
+# %%
 
-# This block imports all the Python libraries we need. These include MNE for M/EEG
-# processing, NumPy for numerical operations, Matplotlib for plotting, and
-# Pathlib for handling file paths. They provide all the basic tools required to
-# load data, run QC, create figures, and build the final HTML report.
-
+import tempfile
 from pathlib import Path
 
 import matplotlib.pyplot as plt
 import numpy as np
+import scipy.ndimage
 
 import mne
-from mne.preprocessing import ICA
-
-"""
-Here we load the MNE sample dataset, which contains raw data, events, evoked
-responses, and anatomical files. Using this dataset allows us to demonstrate how
-to generate a full QC + MNE report without requiring your own data.
-"""
 
 data_path = Path(mne.datasets.sample.data_path(verbose=False))
 sample_dir = data_path / "MEG" / "sample"
 subjects_dir = data_path / "subjects"
 
-raw_fname = sample_dir / "sample_audvis_raw.fif"
-events_fname = sample_dir / "sample_audvis_raw-eve.fif"
-evoked_fname = sample_dir / "sample_audvis-ave.fif"
-cov_fname = sample_dir / "sample_audvis-cov.fif"
-fwd_fname = sample_dir / "sample_audvis-meg-oct-6-fwd.fif"
-inv_fname = sample_dir / "sample_audvis-meg-oct-6-meg-inv.fif"
-trans_fname = sample_dir / "sample_audvis_raw-trans.fif"
-proj_fname = sample_dir / "sample_audvis_ecg-proj.fif"
-
-raw = mne.io.read_raw_fif(raw_fname, preload=True)
-raw.pick_types(meg=True, eeg=True, eog=True, stim=True)
-
-events = mne.read_events(events_fname)
-
-"""
-This function makes a simple static plot of the first few seconds of raw data.
-It avoids the interactive browser and instead gives a quick visual check of
-signal quality, channel behavior, and overall data shape, which is important for
-QC reports.
-"""
-
-
-def make_raw_overview_figure(raw, n_channels=20, duration=10):
-    """Create a Matplotlib-only raw overview."""
-    sfreq = raw.info["sfreq"]
-    start = 0
-    stop = int(duration * sfreq)
-
-    data, times = raw.get_data(start=start, stop=stop, return_times=True)
-    n = min(n_channels, data.shape[0])
-    data = data[:n]
-    data_norm = data / np.max(np.abs(data), axis=1, keepdims=True)
-
-    fig, ax = plt.subplots(figsize=(12, 6))
-    offset = np.arange(n) * 1.5
-    for i in range(n):
-        ax.plot(times, data_norm[i] + offset[i])
-    ax.set_title(f"Raw Data Overview ({n} channels, {duration}s)")
-    ax.set_xlabel("Time (s)")
-    ax.set_ylabel("Channels (offset)")
-    return fig
-
-
-"""
-We create the MNE Report object and add basic QC components: a simple raw
-overview, the power spectral density (PSD) plot, and the sensor layout. These
-plots help verify noise levels, channel availability, and general data quality
-before deeper analysis.
-"""
-
-report = mne.Report(title="QC + Full MNE Report (Clean, No Duplicates)")
-
-fig = make_raw_overview_figure(raw)
-report.add_figure(fig, title="Raw Data Overview")
-plt.close(fig)
-
-psd = raw.compute_psd()
-fig = psd.plot(show=False)
-report.add_figure(fig, title="PSD of Raw Data")
-plt.close(fig)
-
-fig = raw.plot_sensors(show_names=True)
-report.add_figure(fig, title="Sensor Layout")
-plt.close(fig)
-
-"""
-This block loads event markers and creates epochs (short time windows around
-stimulus events). Epochs allow us to check data quality trial-by-trial and
-understand how different conditions were recorded, which is essential in QC.
-"""
-
-event_id = dict(auditory=1, visual=3)
-report.add_events(events, sfreq=raw.info["sfreq"], title="Events Overview")
-
-epochs = mne.Epochs(
-    raw,
-    events,
-    event_id=event_id,
-    tmin=-0.2,
+# %%
+# The basic process for creating an HTML report is to instantiate the
+# :class:`~mne.Report` class and then use one or more of its many methods to
+# add content, one element at a time.
+#
+# You may also use the :meth:`~mne.Report.parse_folder` method to select
+# particular files to include in the report. But more on that later.
+#
+# .. sidebar: Viewing the report
+#
+#    On successful creation of the report, the :meth:`~mne.Report.save` method
+#    will open the HTML in a new tab in your browser. To disable this, use the
+#    ``open_browser=False`` parameter of :meth:`~mne.Report.save`.
+#
+# Adding `~mne.io.Raw` data
+# ^^^^^^^^^^^^^^^^^^^^^^^^^
+#
+# Raw data can be added via the :meth:`mne.Report.add_raw` method. It can
+# operate with a path to a raw file and `~mne.io.Raw` objects, and will
+# produce – among other output – a slider that allows you to scrub through 10
+# equally-spaced 1-second segments of the data:
+#
+# .. warning::
+#    In the following example, we crop the raw data to 60 seconds merely to
+#    speed up processing; this is not usually recommended!
+
+raw_path = sample_dir / "sample_audvis_filt-0-40_raw.fif"
+raw = mne.io.read_raw(raw_path)
+raw.pick(picks=["eeg", "eog", "stim"]).crop(tmax=60).load_data()
+
+report = mne.Report(title="Raw example")
+# This method also accepts a path, e.g., raw=raw_path
+report.add_raw(raw=raw, title="Raw", psd=False)  # omit PSD plot
+report.save("report_raw.html", overwrite=True)
+
+# %%
+# Adding events
+# ^^^^^^^^^^^^^
+#
+# Events can be added via :meth:`mne.Report.add_events`. You also need to
+# supply the sampling frequency used during the recording; this information is
+# used to generate a meaningful time axis.
+
+events_path = sample_dir / "sample_audvis_filt-0-40_raw-eve.fif"
+events = mne.find_events(raw=raw)
+sfreq = raw.info["sfreq"]
+
+report = mne.Report(title="Events example")
+report.add_events(events=events_path, title="Events from Path", sfreq=sfreq)
+report.add_events(events=events, title='Events from "events"', sfreq=sfreq)
+report.save("report_events.html", overwrite=True)
+
+# %%
+# Adding :class:`~mne.Epochs`
+# ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+#
+# Epochs can be added via :meth:`mne.Report.add_epochs`. Note that although
+# this method accepts a path to an epochs file too, in the following example
+# we only add epochs that we create on the fly from raw data. To demonstrate
+# the representation of epochs metadata, we'll add some of that, too.
+
+event_id = {
+    "auditory/left": 1,
+    "auditory/right": 2,
+    "visual/left": 3,
+    "visual/right": 4,
+    "face": 5,
+    "buttonpress": 32,
+}
+
+metadata, _, _ = mne.epochs.make_metadata(
+    events=events, event_id=event_id, tmin=-0.2, tmax=0.5, sfreq=raw.info["sfreq"]
+)
+epochs = mne.Epochs(raw=raw, events=events, event_id=event_id, metadata=metadata)
+
+report = mne.Report(title="Epochs example")
+report.add_epochs(epochs=epochs, title='Epochs from "epochs"')
+report.save("report_epochs.html", overwrite=True)
+
+# %%
+# Adding `~mne.Evoked`
+# ^^^^^^^^^^^^^^^^^^^^
+#
+# Evoked data can be added via :meth:`mne.Report.add_evokeds`. By default, the
+# ``Evoked.comment`` attribute of each evoked will be used as a title. We can
+# specify custom titles via the ``titles`` parameter. Again, this method
+# also accepts the path to an evoked file stored on disk; in the following
+# example, however, we load the evokeds manually first, since we only want to
+# add a subset of them to the report. The evokeds are not baseline-corrected, so we
+# apply baseline correction, too. Lastly, by providing an (optional) noise covariance,
+# we can add plots evokeds that were "whitened" using this covariance matrix.
+#
+# By default, this method will produce topographic plots at 21 equally-spaced time
+# points (or fewer, if the data contains fewer time points). We can adjust this
+# via the ``n_time_points`` parameter.
+
+evoked_path = sample_dir / "sample_audvis-ave.fif"
+cov_path = sample_dir / "sample_audvis-cov.fif"
+
+evokeds = mne.read_evokeds(evoked_path, baseline=(None, 0))
+evokeds_subset = evokeds[:2]  # The first two
+for evoked in evokeds_subset:
+    evoked.pick("eeg")  # just for speed of plotting
+
+report = mne.Report(title="Evoked example")
+report.add_evokeds(
+    evokeds=evokeds_subset,
+    titles=["evoked 1", "evoked 2"],  # Manually specify titles
+    noise_cov=cov_path,
+    n_time_points=5,
+)
+report.save("report_evoked.html", overwrite=True)
+
+# %%
+# Adding `~mne.Covariance`
+# ^^^^^^^^^^^^^^^^^^^^^^^^
+#
+# (Noise) covariance objects can be added via
+# :meth:`mne.Report.add_covariance`. The method accepts `~mne.Covariance`
+# objects and the path to a file on disk. It also expects us to pass an
+# `~mne.Info` object or the path to a file to read the measurement info from,
+# as well as a title.
+
+cov_path = sample_dir / "sample_audvis-cov.fif"
+
+report = mne.Report(title="Covariance example")
+report.add_covariance(cov=cov_path, info=raw_path, title="Covariance")
+report.save("report_cov.html", overwrite=True)
+
+# %%
+# Adding `~mne.Projection` vectors
+# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+#
+# `~mne.Projection` vectors can be added via
+# :meth:`mne.Report.add_projs`. The method requires an `~mne.Info` object
+# (or the path to one) and a title. Projectors found in the `~mne.Info` will
+# be visualized. You may also supply a list of `~mne.Projection` objects or
+# a path to projectors stored on disk. In this case, the channel information
+# is read from the `~mne.Info`, but projectors potentially included will be
+# ignored; instead, only the explicitly passed projectors will be plotted.
+
+ecg_proj_path = sample_dir / "sample_audvis_ecg-proj.fif"
+report = mne.Report(title="Projectors example")
+report.add_projs(info=raw_path, title="Projs from info")
+
+# Now a joint plot
+events = mne.read_events(sample_dir / "sample_audvis_ecg-eve.fif")
+raw_full = mne.io.read_raw(sample_dir / "sample_audvis_raw.fif").crop(0, 60).load_data()
+ecg_evoked = mne.Epochs(
+    raw=raw_full,
+    events=events,
+    tmin=-0.5,
     tmax=0.5,
-    baseline=(None, 0),
-    preload=True,
-    reject=dict(mag=4e-12, eeg=150e-6),
+    baseline=(None, None),
+).average()
+report.img_max_width = None  # do not constrain image width
+report.add_projs(
+    info=ecg_evoked,
+    projs=ecg_proj_path,
+    title="ECG projs from path",
+    joint=True,  # use joint version of the plot
+)
+report.save("report_projs.html", overwrite=True)
+del raw_full, events, ecg_evoked
+
+# %%
+# Adding `~mne.preprocessing.ICA`
+# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+#
+# `~mne.preprocessing.ICA` objects can be added via
+# :meth:`mne.Report.add_ica`. Aside from the parameters ``ica`` (that accepts
+# an `~mne.preprocessing.ICA` instance or a path to an ICA object stored on
+# disk) and the ``title``, there is a third required parameter, ``inst``.
+# ``inst`` is used to specify a `~mne.io.Raw` or `~mne.Epochs` object for
+# producing ICA property plots and overlay plots demonstrating
+# the effects of ICA cleaning. If, instead, you only want to generate ICA
+# component topography plots, explicitly pass ``inst=None``.
+#
+# .. note:: :meth:`mne.Report.add_ica` only works with fitted ICAs.
+#
+# You can optionally specify for which components to produce topography and
+# properties plots by passing ``picks``. By default, all components will be
+# shown. It is also possible to pass evoked signals based on ECG and EOG events
+# via ``ecg_evoked`` and ``eog_evoked``. This allows you directly see the
+# effects of ICA component removal on these artifactual signals.
+# Artifact detection scores produced by
+# :meth:`~mne.preprocessing.ICA.find_bads_ecg`
+# and :meth:`~mne.preprocessing.ICA.find_bads_eog` can be passed via the
+# ``ecg_scores`` and ``eog_scores`` parameters, respectively, producing
+# visualizations of the scores for each ICA component.
+#
+# Lastly, by passing ``n_jobs``, you may largely speed up the generation of
+# the properties plots by enabling parallel execution.
+#
+# .. warning::
+#    In the following example, we request a small number of ICA components
+#    to estimate, set the threshold for assuming ICA convergence to a very
+#    liberal value, and only visualize 2 of the components. All of this is
+#    done to largely reduce the processing time of this tutorial, and is
+#    usually **not** recommended for an actual data analysis.
+
+ica = mne.preprocessing.ICA(
+    n_components=5,  # fit 5 ICA components
+    fit_params=dict(tol=0.01),  # assume very early on that ICA has converged
 )
-report.add_epochs(epochs, title="Epochs Overview")
-
-"""
-Here we fit ICA to identify eye-movement components and mark them for removal.
-We also add ICA diagnostics to the report, such as component maps and EOG
-correlations. ICA is an important step in QC for detecting common artifacts.
-"""
 
-ica = ICA(n_components=20, random_state=97)
-ica.fit(raw)
+ica.fit(inst=raw)
 
-eog_epochs = mne.preprocessing.create_eog_epochs(raw)
-eog_comps, eog_scores = ica.find_bads_eog(eog_epochs, ch_name="EEG 001")
-ica.exclude = eog_comps
+# create epochs based on EOG events, find EOG artifacts in the data via pattern
+# matching, and exclude the EOG-related ICA components
+eog_epochs = mne.preprocessing.create_eog_epochs(raw=raw)
+eog_components, eog_scores = ica.find_bads_eog(
+    inst=eog_epochs,
+    ch_name="EEG 001",  # a channel close to the eye
+    threshold=1,  # lower than the default threshold
+)
+ica.exclude = eog_components
 
+report = mne.Report(title="ICA example")
 report.add_ica(
     ica=ica,
+    title="ICA cleaning",
+    picks=ica.exclude,  # plot the excluded EOG components
     inst=raw,
-    title="ICA Components",
     eog_evoked=eog_epochs.average(),
     eog_scores=eog_scores,
+    n_jobs=None,  # could be increased!
 )
-
-"""
-This section computes evoked responses (averaged brain activity) for auditory and
-visual events and plots topographic maps. It also loads the noise covariance
-matrix and any projectors. Together, these help evaluate data cleanliness and
-prepare for source analysis.
-"""
-
-cov = mne.read_cov(cov_fname)
-evokeds = [epochs[k].average() for k in event_id]
-report.add_evokeds(
-    evokeds, titles=list(event_id.keys()), noise_cov=cov, n_time_points=5
+report.save("report_ica.html", overwrite=True)
+
+# %%
+# Adding MRI with BEM
+# ^^^^^^^^^^^^^^^^^^^
+#
+# MRI slices with superimposed traces of the boundary element model (BEM)
+# surfaces can be added via :meth:`mne.Report.add_bem`. All you need to pass is
+# the FreeSurfer subject name and subjects directory, and a title. To reduce
+# the resulting file size, you may pass the ``decim`` parameter to only include
+# every n-th volume slice, and ``width`` to specify the width of the resulting
+# figures in pixels.
+
+report = mne.Report(title="BEM example")
+report.add_bem(
+    subject="sample",
+    subjects_dir=subjects_dir,
+    title="MRI & BEM",
+    decim=40,
+    width=256,
 )
+report.save("report_mri_and_bem.html", overwrite=True)
+
+# %%
+# Adding coregistration
+# ^^^^^^^^^^^^^^^^^^^^^
+#
+# The sensor alignment (``head -> mri`` transformation obtained by
+# "coregistration") can be visualized via :meth:`mne.Report.add_trans`. The
+# method expects the transformation either as a `~mne.transforms.Transform`
+# object or as a path to a ``trans.fif`` file, the FreeSurfer subject name and
+# subjects directory, and a title. The ``alpha`` parameter can be used to
+# control the transparency of the head, where a value of 1 means fully opaque.
+
+trans_path = sample_dir / "sample_audvis_raw-trans.fif"
+
+report = mne.Report(title="Coregistration example")
+report.add_trans(
+    trans=trans_path,
+    info=raw_path,
+    subject="sample",
+    subjects_dir=subjects_dir,
+    alpha=1.0,
+    title="Coregistration",
+)
+report.save("report_coregistration.html", overwrite=True)
 
-common_chs = list(set(cov.ch_names).intersection(raw.ch_names))
-cov = cov.copy().pick_channels(common_chs)
-report.add_covariance(cov=cov, info=raw.info, title="Noise Covariance")
-
-projs = mne.read_proj(proj_fname)
-report.add_projs(info=raw, projs=projs, title="ECG Projectors")
-
-"""
-Here we try adding anatomical elements like the MRI surfaces (BEM),
-sensor-to-MRI coregistration, and the forward and inverse operators. These steps
-link sensor data to the brain and are needed for source estimation. They are
-wrapped in try/except so the script still runs even if anatomy files are
-missing.
-"""
+# %%
+# Adding a `~mne.Forward` solution
+# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+#
+# Forward solutions ("leadfields") can be added by passing a `~mne.Forward`
+# object or the path to a forward solution stored on disk to
+# meth:`mne.Report.add_forward`.
 
-try:
-    report.add_bem(subject="sample", subjects_dir=subjects_dir, title="MRI & BEM")
-except Exception:
-    print("BEM unavailable.")
-
-try:
-    report.add_trans(
-        trans=trans_fname,
-        info=raw,
-        subject="sample",
-        subjects_dir=subjects_dir,
-        title="Coregistration",
-    )
-except Exception:
-    print("Coreg unavailable.")
-
-try:
-    report.add_forward(
-        forward=fwd_fname,
-        title="Forward Solution",
-        plot=True,
-        subjects_dir=subjects_dir,
-    )
-except Exception:
-    print("Forward unavailable.")
-
-try:
-    report.add_inverse_operator(
-        inverse_operator=inv_fname,
-        title="Inverse Operator",
-        plot=True,
-        subjects_dir=subjects_dir,
-    )
-except Exception:
-    print("Inverse unavailable.")
+fwd_path = sample_dir / "sample_audvis-meg-oct-6-fwd.fif"
 
-"""
-This part adds source-level brain activity snapshots to the report. STCs show
-how brain signals map onto cortex over time, giving a deeper understanding of
-neural responses beyond sensor space.
-"""
+report = mne.Report(title="Forward solution example")
+report.add_forward(
+    forward=fwd_path, title="Forward solution", plot=True, subjects_dir=subjects_dir
+)
+report.save("report_forward_sol.html", overwrite=True)
+
+# %%
+# Adding an `~mne.minimum_norm.InverseOperator`
+# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+#
+# An inverse operator can be added via :meth:`mne.Report.add_inverse_operator`.
+# The method expects an `~mne.minimum_norm.InverseOperator` object or a path to
+# one stored on disk, and a title.
+
+inverse_op_path = sample_dir / "sample_audvis-meg-oct-6-meg-inv.fif"
+
+report = mne.Report(title="Inverse operator example")
+report.add_inverse_operator(
+    inverse_operator=inverse_op_path,
+    title="Inverse operator",
+    plot=True,
+    subjects_dir=subjects_dir,
+)
+report.save("report_inverse_op.html", overwrite=True)
+
+# %%
+# Adding a `~mne.SourceEstimate`
+# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+#
+# An inverse solution (also called source estimate or source time course, STC)
+# can be added via :meth:`mne.Report.add_stc`. The
+# method expects an `~mne.SourceEstimate`, the corresponding FreeSurfer subject
+# name and subjects directory, and a title. By default, it will produce
+# snapshots at 51 equally-spaced time points (or fewer, if the data contains
+# fewer time points). We can adjust this via the ``n_time_points`` parameter.
+
+stc_path = sample_dir / "sample_audvis-meg"
+
+report = mne.Report(title="Source estimate example")
+report.add_stc(
+    stc=stc_path,
+    subject="sample",
+    subjects_dir=subjects_dir,
+    title="Source estimate",
+    n_time_points=2,  # few for speed
+)
+report.save("report_inverse_sol.html", overwrite=True)
+
+# %%
+# Adding source code (e.g., a Python script)
+# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+#
+# It is possible to add code or scripts (e.g., the scripts you used for
+# analysis) to the report via :meth:`mne.Report.add_code`. The code blocks will
+# be automatically syntax-highlighted. You may pass a string with the
+# respective code snippet, or the path to a file. If you pass a path, it
+# **must** be a `pathlib.Path` object (and not a string), otherwise it will be
+# treated as a code literal.
+#
+# Optionally, you can specify which programming language to assume for syntax
+# highlighting by passing the ``language`` parameter. By default, we'll assume
+# the provided code is Python.
+
+mne_init_py_path = Path(mne.__file__)  # __init__.py in the MNE-Python root
+mne_init_py_content = mne_init_py_path.read_text(encoding="utf-8")
+
+report = mne.Report(title="Code example")
+report.add_code(code=mne_init_py_path, title="Code from Path")
+report.add_code(code=mne_init_py_content, title="Code from string")
+
+report.save("report_code.html", overwrite=True)
+
+# %%
+# Adding custom figures
+# ^^^^^^^^^^^^^^^^^^^^^
+#
+# Custom Matplotlib figures can be added via :meth:`~mne.Report.add_figure`.
+# Required parameters are the figure and a title. Optionally, may add a caption
+# to appear below the figure. You can also specify the image format of the
+# image file that will be generated from the figure, so it can be embedded in
+# the HTML report.
+
+x = np.linspace(start=0, stop=10, num=100)
+y = x**2
+
+fig, ax = plt.subplots()
+ax.plot(x, y, ls="--", lw=2, color="blue", label="my function")
+ax.set_xlabel("x")
+ax.set_ylabel("f(x)")
+ax.legend()
+
+report = mne.Report(title="Figure example")
+report.add_figure(
+    fig=fig,
+    title="A custom figure",
+    caption="A blue dashed line reaches up into the sky …",
+    image_format="PNG",
+)
+report.save("report_custom_figure.html", overwrite=True)
+plt.close(fig)
 
-try:
-    stc_path = sample_dir / "sample_audvis-meg"
-    report.add_stc(
-        stc=stc_path,
-        subject="sample",
-        subjects_dir=subjects_dir,
-        title="Source Estimate",
-        n_time_points=2,
+# %%
+# Multiple figures can be grouped into a single section via the ``section``
+# parameter.
+
+fig_1, ax_1 = plt.subplots()
+ax_1.plot([1, 2, 3])
+
+fig_2, ax_2 = plt.subplots()
+ax_2.plot([3, 2, 1])
+
+section = "Section example"
+
+report = mne.Report(title="Figure section example")
+report.add_figure(fig=fig_1, title="Figure 1", section=section, tags="fig-1")
+report.add_figure(fig=fig_2, title="Figure 2", section=section, tags="fig-2")
+report.save("report_custom_figure_sections.html", overwrite=True)
+plt.close(fig_1)
+plt.close(fig_2)
+
+# %%
+# The :meth:`mne.Report.add_figure` method can also add multiple figures at
+# once. In this case, a slider will appear, allowing users to intuitively
+# browse the figures. To make this work, you need to provide a collection o
+# figures, a title, and optionally a collection of captions.
+#
+# In the following example, we will read the MNE logo as a Matplotlib figure
+# and rotate it with different angles. Each rotated figure and its respective
+# caption will be added to a list, which is then used to create the slider.
+
+mne_logo_path = Path(mne.__file__).parent / "icons" / "mne_icon-cropped.png"
+fig_array = plt.imread(mne_logo_path)
+rotation_angles = np.linspace(start=0, stop=360, num=8, endpoint=False)
+
+figs = []
+captions = []
+for angle in rotation_angles:
+    # Rotate and remove some rounding errors to avoid Matplotlib warnings
+    fig_array_rotated = scipy.ndimage.rotate(input=fig_array, angle=angle)
+    fig_array_rotated = fig_array_rotated.clip(min=0, max=1)
+
+    # Create the figure
+    fig, ax = plt.subplots(figsize=(3, 3), layout="constrained")
+    ax.imshow(fig_array_rotated)
+    ax.set_axis_off()
+
+    # Store figure and caption
+    figs.append(fig)
+    captions.append(f"Rotation angle: {round(angle, 1)}°")
+
+report = mne.Report(title="Multiple figures example")
+report.add_figure(fig=figs, title="Fun with figures! 🥳", caption=captions)
+report.save("report_custom_figures.html", overwrite=True)
+for fig in figs:
+    plt.close(fig)
+del figs
+
+# %%
+# Adding image files
+# ^^^^^^^^^^^^^^^^^^
+#
+# Existing images (e.g., photos, screenshots, sketches etc.) can be added
+# to the report via :meth:`mne.Report.add_image`. Supported image formats
+# include JPEG, PNG, GIF, and SVG (and possibly others). Like with Matplotlib
+# figures, you can specify a caption to appear below the image.
+
+report = mne.Report(title="Image example")
+report.add_image(
+    image=mne_logo_path, title="MNE", caption="Powered by 🧠 🧠 🧠 around the world!"
+)
+report.save("report_custom_image.html", overwrite=True)
+
+# %%
+# Working with tags
+# ^^^^^^^^^^^^^^^^^
+#
+# Each ``add_*`` method accepts a keyword parameter ``tags``, which can be
+# used to pass one or more tags to associate with the respective content
+# elements. By default, each ``add_*`` method adds a tag describing the data
+# type, e.g., ``evoked`` or ``source-estimate``. When viewing the HTML report,
+# the ``Filter by tags`` dropdown menu can be used to interactively show or
+# hide content with specific tags. This allows you e.g. to only view
+# ``evoked`` or ``participant-001`` data, should you have added those tags.
+# Visible tags will appear with blue, and hidden tags with gray background
+# color.
+#
+# To toggle the visibility of **all** tags, use the respective checkbox in the
+# ``Filter by tags`` dropdown menu, or press :kbd:`T`.
+
+report = mne.Report(title="Tags example")
+report.add_image(
+    image=mne_logo_path,
+    title="MNE Logo",
+    tags=("image", "mne", "logo", "open-source"),
+)
+report.save("report_tags.html", overwrite=True)
+
+# %%
+# Editing a saved report
+# ^^^^^^^^^^^^^^^^^^^^^^
+#
+# Saving to HTML is a write-only operation, meaning that we cannot read an
+# ``.html`` file back as a :class:`~mne.Report` object. In order to be able
+# to edit a report once it's no longer in-memory in an active Python session,
+# save it as an HDF5 file instead of HTML:
+
+report = mne.Report(title="Saved report example", verbose=True)
+report.add_image(image=mne_logo_path, title="MNE 1")
+report.save("report_partial.hdf5", overwrite=True)
+
+# %%
+# The saved report can be read back and modified or amended. This allows the
+# possibility to e.g. run multiple scripts in a processing pipeline, where each
+# script adds new content to an existing report.
+
+report_from_disk = mne.open_report("report_partial.hdf5")
+report_from_disk.add_image(image=mne_logo_path, title="MNE 2")
+report_from_disk.save("report_partial.hdf5", overwrite=True)
+
+# %%
+# To make this even easier, :class:`mne.Report` can be used as a
+# context manager (note the ``with`` statement)`):
+
+with mne.open_report("report_partial.hdf5") as report:
+    report.add_image(image=mne_logo_path, title="MNE 3")
+    report.save("report_final.html", overwrite=True)
+
+# %%
+# With the context manager, the updated report is also automatically saved
+# back to :file:`report.h5` upon leaving the block.
+#
+# Adding an entire folder of files
+# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+#
+# We also provide a way to add an entire **folder** of files to the report at
+# once, without having to invoke the individual ``add_*`` methods outlined
+# above for each file. This approach, while convenient, provides less
+# flexibility with respect to content ordering, tags, titles, etc.
+#
+# Before getting started with :class:`mne.Report`, make sure the files you want
+# to render follow the filename conventions defined by MNE:
+#
+# .. cssclass:: table-bordered
+# .. rst-class:: midvalign
+#
+# =================================== =========================================
+# Data object                         Filename convention (ends with)
+# =================================== =========================================
+# `~mne.io.Raw`                       ``-raw.fif(.gz)``, ``-raw_sss.fif(.gz)``,
+#                                     ``-raw_tsss.fif(.gz)``,
+#                                     ``_meg.fif(.gz)``, ``_eeg.fif(.gz)``,
+#                                     ``_ieeg.fif(.gz)``
+# events                              ``-eve.fif(.gz)``
+# `~mne.Epochs`                       ``-epo.fif(.gz)``
+# `~mne.Evoked`                       ``-ave.fif(.gz)``
+# `~mne.Covariance`                   ``-cov.fif(.gz)``
+# `~mne.Projection`                   ``-proj.fif(.gz)``
+# `~mne.transforms.Transform`         ``-trans.fif(.gz)``
+# `~mne.Forward`                      ``-fwd.fif(.gz)``
+# `~mne.minimum_norm.InverseOperator` ``-inv.fif(.gz)``
+# `~mne.SourceEstimate`               ``-lh.stc``, ``-rh.stc``
+# =================================== =========================================
+#
+# Alternatively, the dash ``-`` in the filename may be replaced with an
+# underscore ``_`` (except for the ``.stc`` files).
+#
+# For our first example, we'll 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`
+# constructor, but we'll also pass ``render_bem=False`` to the
+# :meth:`~mne.Report.parse_folder` method — otherwise we would get a warning
+# about not being able to render MRI and ``trans`` files without knowing the
+# subject. To save some processing time in this tutorial, we're also going to
+# disable rendering of the butterfly plots for the `~mne.io.Raw` data by
+# passing ``raw_butterfly=False``.
+#
+# Which files are included depends on both the ``pattern`` parameter passed to
+# :meth:`~mne.Report.parse_folder` and also the ``subject`` and
+# ``subjects_dir`` parameters provided to the :class:`~mne.Report` constructor.
+
+report = mne.Report(title="parse_folder example")
+report.parse_folder(
+    data_path=data_path, pattern="*raw.fif", render_bem=False, raw_butterfly=False
+)
+report.save("report_parse_folder_basic.html", overwrite=True)
+
+# %%
+# By default, the power spectral density and SSP projectors of the
+# :class:`~mne.io.Raw` files are not shown to speed up report generation. You
+# can add them by passing ``raw_psd=True`` and ``projs=True`` to the
+# :class:`~mne.Report` constructor. Like in the previous example, we're going
+# to omit the butterfly plots by passing ``raw_butterfly=False``. Lastly, let's
+# also refine our pattern to select only the filtered raw recording (omitting
+# the unfiltered data and the empty-room noise recordings).
+
+pattern = "sample_audvis_filt-0-40_raw.fif"
+report = mne.Report(title="parse_folder example 2", raw_psd=True, projs=True)
+report.parse_folder(
+    data_path=data_path, pattern=pattern, render_bem=False, raw_butterfly=False
+)
+report.save("report_parse_folder_raw_psd_projs.html", overwrite=True)
+
+# %%
+# This time we'll pass a specific ``subject`` and ``subjects_dir`` (even though
+# there's only one subject in the sample dataset) and remove our
+# ``render_bem=False`` parameter so we can see the MRI slices, with BEM
+# contours overlaid on top if available. Since this is computationally
+# expensive, we'll also pass the ``mri_decim`` parameter for the benefit of our
+# documentation servers, and skip processing the :file:`.fif` files.
+
+report = mne.Report(
+    title="parse_folder example 3", subject="sample", subjects_dir=subjects_dir
+)
+report.parse_folder(data_path=data_path, pattern="", mri_decim=40)
+report.save("report_parse_folder_mri_bem.html", overwrite=True)
+
+# %%
+# Now let's look at how :class:`~mne.Report` handles :class:`~mne.Evoked`
+# data (we will skip the MRIs to save computation time).
+#
+# The MNE sample dataset we're using in this example has **not** been
+# baseline-corrected; so let's apply baseline correction this now for the
+# report!
+#
+# To request baseline correction, pass a ``baseline`` argument to
+# `~mne.Report`, which should be a tuple with the starting and ending time of
+# the baseline period. For more details, see the documentation on
+# `~mne.Evoked.apply_baseline`. Here, we will apply baseline correction for a
+# baseline period from the beginning of the time interval to time point zero.
+#
+# Lastly, we want to render the "whitened" evoked data, too. Whitening
+# requires us to specify the path to a covariance matrix file via the
+# ``cov_fname`` parameter of `~mne.Report`.
+#
+# Now, let's put all of this together! Here we use a temporary directory
+# for speed so we can render a single Evoked instance, using just EEG
+# channels.
+
+baseline = (None, 0)
+cov_fname = sample_dir / "sample_audvis-cov.fif"
+pattern = "sample_audvis-ave.fif"
+evoked = mne.read_evokeds(sample_dir / pattern)[0].pick("eeg").decimate(4)
+report = mne.Report(
+    title="parse_folder example 4", baseline=baseline, cov_fname=cov_fname
+)
+with tempfile.TemporaryDirectory() as path:
+    evoked.save(Path(path) / pattern)
+    report.parse_folder(
+        path, pattern=pattern, render_bem=False, n_time_points_evokeds=5
     )
-except Exception:
-    print("STC unavailable.")
-
-"""
-A small HTML block is added to show that reports can include instructions,
-interpretations, or descriptive text. This is useful for documentation,
-explaining results, or guiding collaborators.
-"""
-
-html = """
-<p>Example hypothesis:</p>
+report.save("report_parse_folder_evoked.html", overwrite=True)
+
+# %%
+#
+# Adding custom HTML (e.g., a description text)
+# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+#
+# The :meth:`~mne.Report.add_html` method allows you to add custom HTML to
+# your report. This feature can be very convenient to add short descriptions,
+# lists, or reminders to your report (among many other things you can think
+# of encoding in HTML).
+
+report = mne.Report(title="Report on hypothesis 1")
+
+my_html = """
+<p>We have the following hypothesis:</p>
 <ol>
-<li>Auditory vs Visual differences.</li>
-<li>Predicted N1 amplitude change.</li>
+<li>There is a difference between images showing man-made vs. natural
+environments</li>
+<li>This difference manifests itself most strongly in the amplitude of the
+N1 ERP component</li>
 </ol>
+<p>Below we show several plots and tests of the data.</p>
 """
-report.add_html(html, title="Hypothesis")
-
-"""
-Finally, we add an MNE logo and save the entire report as an HTML file. The
-output is fully interactive, self-contained, and easy to share, combining both
-QC and full MNE processing elements in one report.
-"""
-
-logo_path = Path(mne.__file__).parent / "icons" / "mne_icon-cropped.png"
-report.add_image(logo_path, title="MNE Logo")
 
-report.save("mne_report.html", overwrite=True)
-print("Saved as mne_report.html")
+report.add_html(title="Hypothesis", html=my_html)
+report.save("report_add_html.html", overwrite=True)

From 0f777723d393290de74d2be12f551309ac467596 Mon Sep 17 00:00:00 2001
From: varshaa-1616 <varshaa.1616@gmail.com>
Date: Thu, 18 Dec 2025 19:14:14 +0530
Subject: [PATCH 05/10] Wrap forbidden code for docs build; instructions for
 local execution

---
 .../14_quality_control_report.py              | 368 ++++++++++++++++++
 1 file changed, 368 insertions(+)
 create mode 100644 tutorials/preprocessing/14_quality_control_report.py

diff --git a/tutorials/preprocessing/14_quality_control_report.py b/tutorials/preprocessing/14_quality_control_report.py
new file mode 100644
index 00000000000..e0d1bab5972
--- /dev/null
+++ b/tutorials/preprocessing/14_quality_control_report.py
@@ -0,0 +1,368 @@
+"""
+.. _tut-qc-report:
+
+=============================================
+Quality control (QC) reports with mne.Report
+============================================
+
+Quality control (QC) is the process of systematically inspecting M/EEG data
+before any serious preprocessing, modeling, or source analysis is attempted.
+Poor data quality at this stage will *always* propagate downstream and can
+invalidate results, no matter how sophisticated later analyses may be.
+
+This tutorial demonstrates how to create a **single, narrative QC report**
+using :class:`mne.Report`, focusing on **what should be inspected and how the
+results should be interpreted**, rather than exhaustively covering the API.
+
+We use the MNE sample dataset for demonstration. Not all QC sections are
+applicable to every dataset (e.g., continuous head-position tracking), and
+this tutorial explicitly handles such cases.
+
+Authors: The MNE-Python contributors
+License: BSD-3-Clause
+"""
+
+# %%
+
+from pathlib import Path
+
+import mne
+
+# %%
+# Load the sample dataset
+# ----------------------
+# We load a pre-filtered MEG/EEG recording from the MNE sample dataset.
+# Only channels relevant for QC (MEG, EEG, EOG, stimulus) are retained.
+
+data_path = Path(mne.datasets.sample.data_path(verbose=False))
+sample_dir = data_path / "MEG" / "sample"
+subjects_dir = data_path / "subjects"
+
+raw_path = sample_dir / "sample_audvis_filt-0-40_raw.fif"
+events_path = sample_dir / "sample_audvis_filt-0-40_raw-eve.fif"
+
+raw = mne.io.read_raw(raw_path, preload=True)
+raw.pick(["meg", "eeg", "eog", "stim"])
+
+sfreq = raw.info["sfreq"]
+
+# %%
+# Create the QC report
+# -------------------
+# The report acts as a container that collects figures, tables, and text
+# into a single HTML document.
+
+report = mne.Report(
+    title="Sample dataset – Quality Control report",
+    subject="sample",
+    subjects_dir=subjects_dir,
+)
+
+# %%
+# Dataset overview
+# ----------------
+# A brief overview helps the reviewer immediately understand the scale and
+# basic properties of the dataset.
+
+html_overview = f"""
+
+<ul>
+  <li><b>Sampling frequency:</b> {sfreq:.1f} Hz</li>
+  <li><b>Duration:</b> {raw.times[-1]:.1f} s</li>
+  <li><b>Number of channels:</b> {len(raw.ch_names)}</li>
+</ul>
+<p>
+These values should be checked for consistency with the experimental design.
+Unexpected sampling rates, unusually short recordings, or missing channel
+classes often indicate acquisition or conversion problems.
+</p>
+"""
+
+report.add_html(
+    title="Overview",
+    html=html_overview,
+    tags=("qc", "overview"),
+)
+
+# %%
+# Raw data inspection
+# -------------------
+# Visual inspection of raw data is the single most important QC step.
+# Here we inspect both the time series and the power spectral density (PSD).
+
+report.add_raw(
+    raw,
+    title="Raw data overview",
+    psd=True,
+    tags=("qc", "raw"),
+)
+
+# Interpretation:
+# - Look for channels with unusually large amplitudes or flat signals.
+# - In the PSD, check for excessive low-frequency drift, strong line noise,
+# or abnormal spectral shapes compared to neighboring channels.
+
+# %%
+# Events and stimulus timing
+# --------------------------
+# Correct event detection is crucial for all subsequent epoch-based analyses.
+
+events = mne.find_events(raw)
+
+report.add_events(
+    events,
+    sfreq=sfreq,
+    title="Detected events",
+    tags=("qc", "events"),
+)
+
+# Interpretation:
+# - Verify that the number of events matches expectations.
+# - Check that event timing is plausible and evenly distributed.
+# - Missing or duplicated events often indicate trigger channel issues.
+# %%
+
+# Epoching and rejection statistics
+# --------------------------------
+# Epoching allows inspection of data segments time-locked to events, along
+# with automated rejection based on amplitude thresholds.
+
+event_id = {
+    "auditory/left": 1,
+    "auditory/right": 2,
+    "visual/left": 3,
+    "visual/right": 4,
+}
+
+epochs = mne.Epochs(
+    raw,
+    events,
+    event_id=event_id,
+    tmin=-0.2,
+    tmax=0.5,
+    baseline=(None, 0),
+    reject=dict(eeg=150e-6),
+    preload=True,
+)
+
+report.add_epochs(
+    epochs,
+    title="Epochs and rejection statistics",
+    tags=("qc", "epochs"),
+)
+
+# Interpretation:
+# - Excessive rejection rates suggest noisy data or overly strict thresholds.
+# - Rejected epochs should be visually inspected to confirm true artifacts.
+
+# %%
+# Evoked responses
+# ----------------
+# Averaged responses should show physiologically plausible waveforms and
+# reasonable signal-to-noise ratios.
+
+cov_path = sample_dir / "sample_audvis-cov.fif"
+evokeds = mne.read_evokeds(
+    sample_dir / "sample_audvis-ave.fif",
+    baseline=(None, 0),
+)
+
+report.add_evokeds(
+    evokeds=evokeds[:2],
+    noise_cov=cov_path,
+    n_time_points=5,
+    tags=("qc", "evoked"),
+)
+
+# Interpretation:
+# - Check that evoked responses have the expected polarity and timing.
+# - Absence of clear evoked structure may indicate poor data quality or
+# incorrect event definitions.
+
+# %%
+# ICA for artifact inspection
+# ---------------------------
+# Independent Component Analysis (ICA) helps identify stereotypical artifacts
+# such as eye blinks and eye movements.
+
+report.add_html(
+    title="ICA for artifact inspection (run locally)",
+    html="""
+<p>
+ICA fitting is computationally expensive and therefore <b>not executed
+during documentation builds</b>. To inspect ICA components locally,
+copy and run the following code in your own Python session:
+</p>
+
+<pre><code class="python">
+import mne
+
+ica = mne.preprocessing.ICA(
+    n_components=15,
+    random_state=97,
+    max_iter="auto",
+)
+ica.fit(raw)
+
+eog_epochs = mne.preprocessing.create_eog_epochs(raw)
+eog_inds, eog_scores = ica.find_bads_eog(eog_epochs)
+ica.exclude = eog_inds
+
+report.add_ica(
+    ica=ica,
+    inst=raw,
+    title="ICA components (EOG-related artifacts)",
+    tags=("qc", "ica"),
+)
+</code></pre>
+""",
+    tags=("qc", "ica"),
+)
+
+
+# Interpretation:
+# - Components correlated with EOG should show frontal topographies and
+# stereotyped time courses.
+# - Only components clearly associated with artifacts should be excluded.
+
+# %%
+# Head position / HPI quality control
+# ----------------------------------
+# Continuous head-position tracking (cHPI) allows monitoring subject movement
+# during MEG acquisition. Not all datasets contain usable cHPI information.
+# This sample dataset does not contain usable cHPI information.
+
+report.add_html(
+    title="Head position / HPI (run locally)",
+    html="""
+<p>
+Continuous head-position tracking (cHPI) estimation is not executed in the
+documentation build environment. If your dataset contains cHPI information,
+you can run the following code locally:
+</p>
+
+<pre><code class="python">
+head_pos = mne.chpi.compute_head_pos(raw.info, raw)
+fig = mne.viz.plot_head_positions(
+    head_pos,
+    mode="traces",
+    show=True,
+)
+</code></pre>
+
+<p>
+Stable traces indicate minimal head movement. Large drifts suggest
+movement-related artifacts.
+</p>
+""",
+    tags=("qc", "hpi"),
+)
+
+
+# Interpretation:
+# - Stable traces indicate minimal head movement.
+# - Large translations or rotations suggest movement-related artifacts and
+# may motivate movement compensation or data exclusion.
+
+# %%
+# MEG–MRI coregistration
+# ---------------------
+# Accurate coregistration is critical for source localization.
+
+report.add_html(
+    title="MEG–MRI coregistration (run locally)",
+    html="""
+<p>
+Coregistration visualization requires access to MRI surfaces and interactive
+rendering, which are unavailable in documentation builds.
+Run the following code locally to inspect coregistration quality:
+</p>
+
+<pre><code class="python">
+trans_path = sample_dir / "sample_audvis_raw-trans.fif"
+report.add_trans(
+    trans=trans_path,
+    info=raw_path,
+    subject="sample",
+    subjects_dir=subjects_dir,
+)
+</code></pre>
+""",
+    tags=("qc", "coreg"),
+)
+
+
+# Interpretation:
+# - Head shape points should align well with the MRI scalp surface.
+# - Systematic misalignment indicates digitization or transformation errors.
+
+# %%
+# MRI and BEM surfaces
+# -------------------
+# Boundary Element Method (BEM) surfaces define the head model used for
+# forward and inverse solutions.
+
+report.add_html(
+    title="MRI and BEM surfaces (run locally)",
+    html="""
+<p>
+BEM surface visualization is not executed during documentation builds.
+To inspect BEM surfaces locally, run:
+</p>
+
+<pre><code class="python">
+report.add_bem(
+    subject="sample",
+    subjects_dir=subjects_dir,
+    decim=40,
+)
+</code></pre>
+""",
+    tags=("qc", "bem"),
+)
+
+
+# Interpretation:
+# - Surfaces should be smooth, closed, and non-intersecting.
+# - Poorly formed surfaces can severely degrade source estimates.
+
+# %%
+# Summary
+# -------
+# A concise summary provides a checklist-style confirmation of completed QC.
+
+html_summary = """
+
+<ul>
+  <li>Raw data and spectra inspected</li>
+  <li>Events and epoch rejection verified</li>
+  <li>Evoked responses checked for plausibility</li>
+  <li>ICA components reviewed for artifacts</li>
+  <li>Head position stability assessed (if available)</li>
+  <li>Coregistration and BEM validated</li>
+</ul>
+<p>
+For automated, large-scale QC across BIDS datasets, see the reports generated
+by <code>mne-bids-pipeline</code>, which follow a similar philosophy but operate
+at scale.
+</p>
+"""
+
+report.add_html(
+    title="QC summary",
+    html=html_summary,
+    tags=("qc", "summary"),
+)
+
+# %%
+# Save report
+# -----------
+
+# %%
+# Save report (local use only)
+# ----------------------------
+# Writing files is disabled during documentation builds.
+# Run this script locally to generate the HTML report.
+
+if __name__ == "__main__":
+    report.save("qc_report.html", overwrite=True)

From df423a875b003daa564e2e8ba7c91add3be0f46d Mon Sep 17 00:00:00 2001
From: varshaa-1616 <varshaa.1616@gmail.com>
Date: Sat, 20 Dec 2025 21:17:37 +0530
Subject: [PATCH 06/10] DOC: add QC-focused tutorial using mne.Report

---
 .../14_quality_control_report.py              | 102 +++++++++++-------
 1 file changed, 61 insertions(+), 41 deletions(-)

diff --git a/tutorials/preprocessing/14_quality_control_report.py b/tutorials/preprocessing/14_quality_control_report.py
index e0d1bab5972..5f313f34fe7 100644
--- a/tutorials/preprocessing/14_quality_control_report.py
+++ b/tutorials/preprocessing/14_quality_control_report.py
@@ -6,27 +6,44 @@
 ============================================
 
 Quality control (QC) is the process of systematically inspecting M/EEG data
-before any serious preprocessing, modeling, or source analysis is attempted.
-Poor data quality at this stage will *always* propagate downstream and can
-invalidate results, no matter how sophisticated later analyses may be.
+**throughout all stages of an analysis pipeline**, including raw data,
+intermediate preprocessing steps, and derived results.
+
+While QC often begins with an initial inspection of the raw recording,
+it is equally important to verify that signals continue to "look reasonable"
+after operations such as filtering, artifact correction, epoching, and
+averaging. Issues introduced or missed at any stage can propagate downstream
+and invalidate later analyses.
 
 This tutorial demonstrates how to create a **single, narrative QC report**
 using :class:`mne.Report`, focusing on **what should be inspected and how the
 results should be interpreted**, rather than exhaustively covering the API.
 
+For clarity and reproducibility, the examples below focus on common QC checks
+applied at representative stages of an analysis pipeline. The same reporting
+approach can—and should—be reused whenever new processing steps are applied.
+
 We use the MNE sample dataset for demonstration. Not all QC sections are
 applicable to every dataset (e.g., continuous head-position tracking), and
 this tutorial explicitly handles such cases.
 
-Authors: The MNE-Python contributors
-License: BSD-3-Clause
+Note:
+The generated HTML report is intended to be opened directly in a browser.
+Some interactive elements (e.g., sliders) may not function correctly
+when the file is served via a local HTTP server.
+
+
 """
 
+# Authors: The MNE-Python contributors
+# License: BSD-3-Clause
+
 # %%
 
 from pathlib import Path
 
 import mne
+from mne.preprocessing import ICA, create_eog_epochs
 
 # %%
 # Load the sample dataset
@@ -39,12 +56,15 @@
 subjects_dir = data_path / "subjects"
 
 raw_path = sample_dir / "sample_audvis_filt-0-40_raw.fif"
-events_path = sample_dir / "sample_audvis_filt-0-40_raw-eve.fif"
+
 
 raw = mne.io.read_raw(raw_path, preload=True)
+
+# Retain only channels relevant for QC to simplify visualization and
+# focus inspection on signals typically reviewed during data quality checks.
 raw.pick(["meg", "eeg", "eog", "stim"])
 
-sfreq = raw.info["sfreq"]
+sfreq = raw.info["sfreq"]  # Sampling Frequency (Hz)
 
 # %%
 # Create the QC report
@@ -179,48 +199,45 @@
 # - Absence of clear evoked structure may indicate poor data quality or
 # incorrect event definitions.
 
+
 # %%
 # ICA for artifact inspection
 # ---------------------------
-# Independent Component Analysis (ICA) helps identify stereotypical artifacts
-# such as eye blinks and eye movements.
-
-report.add_html(
-    title="ICA for artifact inspection (run locally)",
-    html="""
-<p>
-ICA fitting is computationally expensive and therefore <b>not executed
-during documentation builds</b>. To inspect ICA components locally,
-copy and run the following code in your own Python session:
-</p>
-
-<pre><code class="python">
-import mne
-
-ica = mne.preprocessing.ICA(
+# Independent Component Analysis (ICA) can be used during QC to identify
+# stereotypical artifacts such as eye blinks and eye movements.
+#
+# For QC purposes, ICA is typically run with a lightweight configuration
+# (e.g., fewer components or temporal decimation) to provide rapid feedback
+# on data quality, rather than an optimized decomposition for final analysis.
+
+ica = ICA(
     n_components=15,
     random_state=97,
     max_iter="auto",
 )
-ica.fit(raw)
 
-eog_epochs = mne.preprocessing.create_eog_epochs(raw)
+# Fit ICA using a decimated signal for speed
+ica.fit(raw, picks=("meg", "eeg"), decim=3)
+
+
+# Identify EOG-related components
+eog_epochs = create_eog_epochs(raw)
 eog_inds, eog_scores = ica.find_bads_eog(eog_epochs)
 ica.exclude = eog_inds
 
 report.add_ica(
     ica=ica,
-    inst=raw,
-    title="ICA components (EOG-related artifacts)",
+    inst=epochs,
+    title="ICA components (artifact inspection)",
     tags=("qc", "ica"),
 )
-</code></pre>
-""",
-    tags=("qc", "ica"),
-)
-
 
 # Interpretation:
+# - Use the topographic maps to identify spatial patterns characteristic
+#   of artifacts (e.g., frontal patterns for eye blinks).
+# - The component property viewer is intended for detailed inspection of
+#   individual components and is most informative when combined with
+# qe epoched data or explicit artifact scoring.
 # - Components correlated with EOG should show frontal topographies and
 # stereotyped time courses.
 # - Only components clearly associated with artifacts should be excluded.
@@ -236,8 +253,9 @@
     title="Head position / HPI (run locally)",
     html="""
 <p>
-Continuous head-position tracking (cHPI) estimation is not executed in the
-documentation build environment. If your dataset contains cHPI information,
+Continuous head-position tracking (cHPI) estimation can be computationally
+expensive and is therefore typically run selectively during QC.
+If your dataset contains cHPI information,
 you can run the following code locally:
 </p>
 
@@ -274,7 +292,7 @@
     html="""
 <p>
 Coregistration visualization requires access to MRI surfaces and interactive
-rendering, which are unavailable in documentation builds.
+rendering, which require MRI surfaces and interactive 3D visualization.
 Run the following code locally to inspect coregistration quality:
 </p>
 
@@ -306,7 +324,8 @@
     title="MRI and BEM surfaces (run locally)",
     html="""
 <p>
-BEM surface visualization is not executed during documentation builds.
+BEM surface visualization is typically performed interactively when preparing
+source-space analyses.
 To inspect BEM surfaces locally, run:
 </p>
 
@@ -359,10 +378,11 @@
 # -----------
 
 # %%
-# Save report (local use only)
+# Save report
 # ----------------------------
-# Writing files is disabled during documentation builds.
 # Run this script locally to generate the HTML report.
-
-if __name__ == "__main__":
-    report.save("qc_report.html", overwrite=True)
+report.save(
+    "qc_report.html",
+    overwrite=True,
+    open_browser=False,
+)

From fc6036a29178b8ddfad2f6bb60737752e6ee8d1a Mon Sep 17 00:00:00 2001
From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com>
Date: Wed, 24 Dec 2025 03:36:20 +0000
Subject: [PATCH 07/10] [autofix.ci] apply automated fixes

---
 tutorials/preprocessing/14_quality_control_report.py | 1 +
 1 file changed, 1 insertion(+)

diff --git a/tutorials/preprocessing/14_quality_control_report.py b/tutorials/preprocessing/14_quality_control_report.py
index 5f313f34fe7..1f3d162b02e 100644
--- a/tutorials/preprocessing/14_quality_control_report.py
+++ b/tutorials/preprocessing/14_quality_control_report.py
@@ -37,6 +37,7 @@
 
 # Authors: The MNE-Python contributors
 # License: BSD-3-Clause
+# Copyright the MNE-Python contributors.
 
 # %%
 

From 91b50c84037aad8e36529f36b15ab4687f794d48 Mon Sep 17 00:00:00 2001
From: Eric Larson <larson.eric.d@gmail.com>
Date: Tue, 6 Jan 2026 10:30:20 -0500
Subject: [PATCH 08/10] FIX: Fixes for headings

---
 .../14_quality_control_report.py              | 25 ++++++-------------
 1 file changed, 7 insertions(+), 18 deletions(-)

diff --git a/tutorials/preprocessing/14_quality_control_report.py b/tutorials/preprocessing/14_quality_control_report.py
index 1f3d162b02e..462f282a094 100644
--- a/tutorials/preprocessing/14_quality_control_report.py
+++ b/tutorials/preprocessing/14_quality_control_report.py
@@ -1,7 +1,7 @@
 """
 .. _tut-qc-report:
 
-=============================================
+============================================
 Quality control (QC) reports with mne.Report
 ============================================
 
@@ -26,13 +26,6 @@
 We use the MNE sample dataset for demonstration. Not all QC sections are
 applicable to every dataset (e.g., continuous head-position tracking), and
 this tutorial explicitly handles such cases.
-
-Note:
-The generated HTML report is intended to be opened directly in a browser.
-Some interactive elements (e.g., sliders) may not function correctly
-when the file is served via a local HTTP server.
-
-
 """
 
 # Authors: The MNE-Python contributors
@@ -48,7 +41,7 @@
 
 # %%
 # Load the sample dataset
-# ----------------------
+# -----------------------
 # We load a pre-filtered MEG/EEG recording from the MNE sample dataset.
 # Only channels relevant for QC (MEG, EEG, EOG, stimulus) are retained.
 
@@ -69,7 +62,7 @@
 
 # %%
 # Create the QC report
-# -------------------
+# --------------------
 # The report acts as a container that collects figures, tables, and text
 # into a single HTML document.
 
@@ -144,7 +137,7 @@
 # %%
 
 # Epoching and rejection statistics
-# --------------------------------
+# ---------------------------------
 # Epoching allows inspection of data segments time-locked to events, along
 # with automated rejection based on amplitude thresholds.
 
@@ -245,7 +238,7 @@
 
 # %%
 # Head position / HPI quality control
-# ----------------------------------
+# -----------------------------------
 # Continuous head-position tracking (cHPI) allows monitoring subject movement
 # during MEG acquisition. Not all datasets contain usable cHPI information.
 # This sample dataset does not contain usable cHPI information.
@@ -285,7 +278,7 @@
 
 # %%
 # MEG–MRI coregistration
-# ---------------------
+# ----------------------
 # Accurate coregistration is critical for source localization.
 
 report.add_html(
@@ -317,7 +310,7 @@
 
 # %%
 # MRI and BEM surfaces
-# -------------------
+# --------------------
 # Boundary Element Method (BEM) surfaces define the head model used for
 # forward and inverse solutions.
 
@@ -377,10 +370,6 @@
 # %%
 # Save report
 # -----------
-
-# %%
-# Save report
-# ----------------------------
 # Run this script locally to generate the HTML report.
 report.save(
     "qc_report.html",

From 9ad0ab617ed7d533602e050a96513bdd9f989f14 Mon Sep 17 00:00:00 2001
From: Eric Larson <larson.eric.d@gmail.com>
Date: Wed, 7 Jan 2026 12:33:42 -0500
Subject: [PATCH 09/10] DOC: Cleaner

---
 .../14_quality_control_report.py              | 257 ++++++------------
 1 file changed, 76 insertions(+), 181 deletions(-)

diff --git a/tutorials/preprocessing/14_quality_control_report.py b/tutorials/preprocessing/14_quality_control_report.py
index 462f282a094..fab5c5e3edf 100644
--- a/tutorials/preprocessing/14_quality_control_report.py
+++ b/tutorials/preprocessing/14_quality_control_report.py
@@ -25,8 +25,12 @@
 
 We use the MNE sample dataset for demonstration. Not all QC sections are
 applicable to every dataset (e.g., continuous head-position tracking), and
-this tutorial explicitly handles such cases.
-"""
+this tutorial explicitly handles such cases. We will also save the report after each
+step so that it can be viewed in the browser after each code block is run.
+
+.. note:: For several additional examples of complete reports, see the
+   `MNE-BIDS-Pipeline QC reports <https://mne.tools/mne-bids-pipeline/stable/examples/examples.html>`_.
+"""  # noqa: E501
 
 # Authors: The MNE-Python contributors
 # License: BSD-3-Clause
@@ -46,13 +50,17 @@
 # Only channels relevant for QC (MEG, EEG, EOG, stimulus) are retained.
 
 data_path = Path(mne.datasets.sample.data_path(verbose=False))
-sample_dir = data_path / "MEG" / "sample"
+subject = "sample"
+sample_dir = data_path / "MEG" / subject
 subjects_dir = data_path / "subjects"
 
 raw_path = sample_dir / "sample_audvis_filt-0-40_raw.fif"
 
 
-raw = mne.io.read_raw(raw_path, preload=True)
+raw = mne.io.read_raw(raw_path)
+
+# We will also crop the dataset for speed
+raw.crop(0, 60).load_data()
 
 # Retain only channels relevant for QC to simplify visualization and
 # focus inspection on signals typically reviewed during data quality checks.
@@ -67,8 +75,8 @@
 # into a single HTML document.
 
 report = mne.Report(
-    title="Sample dataset – Quality Control report",
-    subject="sample",
+    title="Sample dataset - Quality Control report",
+    subject=subject,
     subjects_dir=subjects_dir,
 )
 
@@ -78,48 +86,48 @@
 # A brief overview helps the reviewer immediately understand the scale and
 # basic properties of the dataset.
 
-html_overview = f"""
-
-<ul>
-  <li><b>Sampling frequency:</b> {sfreq:.1f} Hz</li>
-  <li><b>Duration:</b> {raw.times[-1]:.1f} s</li>
-  <li><b>Number of channels:</b> {len(raw.ch_names)}</li>
-</ul>
-<p>
-These values should be checked for consistency with the experimental design.
-Unexpected sampling rates, unusually short recordings, or missing channel
-classes often indicate acquisition or conversion problems.
-</p>
+html_overview = """
+This report presents a quality control (QC) overview of the MNE sample dataset.<br><br>
+For information about the paradigm, see
+<a href="https://mne.tools/stable/documentation/datasets.html#sample">the MNE docs</a>.
 """
 
 report.add_html(
     title="Overview",
     html=html_overview,
-    tags=("qc", "overview"),
+    tags=("overview"),
+)
+save_kwargs = dict(
+    overwrite=True,
+    open_browser=False,
 )
+report.save("qc_report_1.html", **save_kwargs)
 
 # %%
 # Raw data inspection
 # -------------------
 # Visual inspection of raw data is the single most important QC step.
 # Here we inspect both the time series and the power spectral density (PSD).
+#
+# - Look for channels with unusually large amplitudes or flat signals.
+# - In the PSD, check for excessive low-frequency drift, strong line noise,
+#   or abnormal spectral shapes compared to neighboring channels.
 
 report.add_raw(
     raw,
     title="Raw data overview",
-    psd=True,
-    tags=("qc", "raw"),
+    psd=False,  # omit just for speed here
 )
-
-# Interpretation:
-# - Look for channels with unusually large amplitudes or flat signals.
-# - In the PSD, check for excessive low-frequency drift, strong line noise,
-# or abnormal spectral shapes compared to neighboring channels.
+report.save("qc_report_2.html", **save_kwargs)
 
 # %%
 # Events and stimulus timing
 # --------------------------
 # Correct event detection is crucial for all subsequent epoch-based analyses.
+#
+# - Verify that the number of events matches expectations.
+# - Check that event timing is plausible and evenly distributed.
+# - Missing or duplicated events often indicate trigger channel issues.
 
 events = mne.find_events(raw)
 
@@ -127,15 +135,10 @@
     events,
     sfreq=sfreq,
     title="Detected events",
-    tags=("qc", "events"),
 )
+report.save("qc_report_3.html", **save_kwargs)
 
-# Interpretation:
-# - Verify that the number of events matches expectations.
-# - Check that event timing is plausible and evenly distributed.
-# - Missing or duplicated events often indicate trigger channel issues.
 # %%
-
 # Epoching and rejection statistics
 # ---------------------------------
 # Epoching allows inspection of data segments time-locked to events, along
@@ -162,36 +165,32 @@
 report.add_epochs(
     epochs,
     title="Epochs and rejection statistics",
-    tags=("qc", "epochs"),
 )
-
-# Interpretation:
-# - Excessive rejection rates suggest noisy data or overly strict thresholds.
-# - Rejected epochs should be visually inspected to confirm true artifacts.
+report.save("qc_report_4.html", **save_kwargs)
 
 # %%
 # Evoked responses
 # ----------------
 # Averaged responses should show physiologically plausible waveforms and
 # reasonable signal-to-noise ratios.
+#
+# - Check that evoked responses have the expected polarity and timing.
+# - Absence of clear evoked structure may indicate poor data quality or
+#   incorrect event definitions.
 
 cov_path = sample_dir / "sample_audvis-cov.fif"
-evokeds = mne.read_evokeds(
+evoked = mne.read_evokeds(
     sample_dir / "sample_audvis-ave.fif",
     baseline=(None, 0),
-)
+)[0]  # just one for speed
+evoked.decimate(4)  # also for speed
 
 report.add_evokeds(
-    evokeds=evokeds[:2],
+    evokeds=evoked,
     noise_cov=cov_path,
     n_time_points=5,
-    tags=("qc", "evoked"),
 )
-
-# Interpretation:
-# - Check that evoked responses have the expected polarity and timing.
-# - Absence of clear evoked structure may indicate poor data quality or
-# incorrect event definitions.
+report.save("qc_report_5.html", **save_kwargs)
 
 
 # %%
@@ -203,15 +202,24 @@
 # For QC purposes, ICA is typically run with a lightweight configuration
 # (e.g., fewer components or temporal decimation) to provide rapid feedback
 # on data quality, rather than an optimized decomposition for final analysis.
+#
+# - Use the topographic maps to identify spatial patterns characteristic
+#   of artifacts (e.g., frontal patterns for eye blinks).
+# - The component property viewer is intended for detailed inspection of
+#   individual components and is most informative when combined with
+#   epoched data or explicit artifact scoring.
+# - Components correlated with EOG should show frontal topographies and
+#   stereotyped time courses.
+# - Only components clearly associated with artifacts should be excluded.
 
 ica = ICA(
     n_components=15,
     random_state=97,
-    max_iter="auto",
+    max_iter=50,  # just for speed!
 )
 
 # Fit ICA using a decimated signal for speed
-ica.fit(raw, picks=("meg", "eeg"), decim=3)
+ica.fit(raw, picks=("meg", "eeg"), decim=10, verbose="error")
 
 
 # Identify EOG-related components
@@ -222,157 +230,44 @@
 report.add_ica(
     ica=ica,
     inst=epochs,
+    eog_evoked=eog_epochs.average(),
+    eog_scores=eog_scores,
     title="ICA components (artifact inspection)",
-    tags=("qc", "ica"),
-)
-
-# Interpretation:
-# - Use the topographic maps to identify spatial patterns characteristic
-#   of artifacts (e.g., frontal patterns for eye blinks).
-# - The component property viewer is intended for detailed inspection of
-#   individual components and is most informative when combined with
-# qe epoched data or explicit artifact scoring.
-# - Components correlated with EOG should show frontal topographies and
-# stereotyped time courses.
-# - Only components clearly associated with artifacts should be excluded.
-
-# %%
-# Head position / HPI quality control
-# -----------------------------------
-# Continuous head-position tracking (cHPI) allows monitoring subject movement
-# during MEG acquisition. Not all datasets contain usable cHPI information.
-# This sample dataset does not contain usable cHPI information.
-
-report.add_html(
-    title="Head position / HPI (run locally)",
-    html="""
-<p>
-Continuous head-position tracking (cHPI) estimation can be computationally
-expensive and is therefore typically run selectively during QC.
-If your dataset contains cHPI information,
-you can run the following code locally:
-</p>
-
-<pre><code class="python">
-head_pos = mne.chpi.compute_head_pos(raw.info, raw)
-fig = mne.viz.plot_head_positions(
-    head_pos,
-    mode="traces",
-    show=True,
-)
-</code></pre>
-
-<p>
-Stable traces indicate minimal head movement. Large drifts suggest
-movement-related artifacts.
-</p>
-""",
-    tags=("qc", "hpi"),
 )
-
-
-# Interpretation:
-# - Stable traces indicate minimal head movement.
-# - Large translations or rotations suggest movement-related artifacts and
-# may motivate movement compensation or data exclusion.
+report.save("qc_report_6.html", **save_kwargs)
 
 # %%
 # MEG–MRI coregistration
 # ----------------------
 # Accurate coregistration is critical for source localization.
+#
+# - Head shape points should align well with the MRI scalp surface.
+# - Systematic misalignment indicates digitization or transformation errors.
 
-report.add_html(
-    title="MEG–MRI coregistration (run locally)",
-    html="""
-<p>
-Coregistration visualization requires access to MRI surfaces and interactive
-rendering, which require MRI surfaces and interactive 3D visualization.
-Run the following code locally to inspect coregistration quality:
-</p>
-
-<pre><code class="python">
-trans_path = sample_dir / "sample_audvis_raw-trans.fif"
+
+trans = sample_dir / "sample_audvis_raw-trans.fif"
 report.add_trans(
-    trans=trans_path,
-    info=raw_path,
-    subject="sample",
+    trans,
+    info=raw.info,
+    title="MEG–MRI-head coregistration",
+    subject=subject,
     subjects_dir=subjects_dir,
 )
-</code></pre>
-""",
-    tags=("qc", "coreg"),
-)
-
-
-# Interpretation:
-# - Head shape points should align well with the MRI scalp surface.
-# - Systematic misalignment indicates digitization or transformation errors.
+report.save("qc_report_7.html", **save_kwargs)
 
 # %%
 # MRI and BEM surfaces
 # --------------------
 # Boundary Element Method (BEM) surfaces define the head model used for
 # forward and inverse solutions.
-
-report.add_html(
-    title="MRI and BEM surfaces (run locally)",
-    html="""
-<p>
-BEM surface visualization is typically performed interactively when preparing
-source-space analyses.
-To inspect BEM surfaces locally, run:
-</p>
-
-<pre><code class="python">
-report.add_bem(
-    subject="sample",
-    subjects_dir=subjects_dir,
-    decim=40,
-)
-</code></pre>
-""",
-    tags=("qc", "bem"),
-)
-
-
-# Interpretation:
+#
 # - Surfaces should be smooth, closed, and non-intersecting.
 # - Poorly formed surfaces can severely degrade source estimates.
 
-# %%
-# Summary
-# -------
-# A concise summary provides a checklist-style confirmation of completed QC.
-
-html_summary = """
-
-<ul>
-  <li>Raw data and spectra inspected</li>
-  <li>Events and epoch rejection verified</li>
-  <li>Evoked responses checked for plausibility</li>
-  <li>ICA components reviewed for artifacts</li>
-  <li>Head position stability assessed (if available)</li>
-  <li>Coregistration and BEM validated</li>
-</ul>
-<p>
-For automated, large-scale QC across BIDS datasets, see the reports generated
-by <code>mne-bids-pipeline</code>, which follow a similar philosophy but operate
-at scale.
-</p>
-"""
-
-report.add_html(
-    title="QC summary",
-    html=html_summary,
-    tags=("qc", "summary"),
-)
-
-# %%
-# Save report
-# -----------
-# Run this script locally to generate the HTML report.
-report.save(
-    "qc_report.html",
-    overwrite=True,
-    open_browser=False,
+report.add_bem(
+    subject,
+    subjects_dir=subjects_dir,
+    title="BEM surfaces",
+    decim=20,  # for speed
 )
+report.save("qc_report_8.html", **save_kwargs)

From 9edf37a0819458bbadb3fae6ecbb3b7176386b80 Mon Sep 17 00:00:00 2001
From: Eric Larson <larson.eric.d@gmail.com>
Date: Wed, 7 Jan 2026 13:25:55 -0500
Subject: [PATCH 10/10] FIX: Better

---
 .../14_quality_control_report.py              | 22 +++++++------------
 1 file changed, 8 insertions(+), 14 deletions(-)

diff --git a/tutorials/preprocessing/14_quality_control_report.py b/tutorials/preprocessing/14_quality_control_report.py
index fab5c5e3edf..1880ae014b2 100644
--- a/tutorials/preprocessing/14_quality_control_report.py
+++ b/tutorials/preprocessing/14_quality_control_report.py
@@ -25,8 +25,7 @@
 
 We use the MNE sample dataset for demonstration. Not all QC sections are
 applicable to every dataset (e.g., continuous head-position tracking), and
-this tutorial explicitly handles such cases. We will also save the report after each
-step so that it can be viewed in the browser after each code block is run.
+this tutorial explicitly handles such cases.
 
 .. note:: For several additional examples of complete reports, see the
    `MNE-BIDS-Pipeline QC reports <https://mne.tools/mne-bids-pipeline/stable/examples/examples.html>`_.
@@ -97,11 +96,6 @@
     html=html_overview,
     tags=("overview"),
 )
-save_kwargs = dict(
-    overwrite=True,
-    open_browser=False,
-)
-report.save("qc_report_1.html", **save_kwargs)
 
 # %%
 # Raw data inspection
@@ -118,7 +112,6 @@
     title="Raw data overview",
     psd=False,  # omit just for speed here
 )
-report.save("qc_report_2.html", **save_kwargs)
 
 # %%
 # Events and stimulus timing
@@ -136,7 +129,6 @@
     sfreq=sfreq,
     title="Detected events",
 )
-report.save("qc_report_3.html", **save_kwargs)
 
 # %%
 # Epoching and rejection statistics
@@ -166,7 +158,6 @@
     epochs,
     title="Epochs and rejection statistics",
 )
-report.save("qc_report_4.html", **save_kwargs)
 
 # %%
 # Evoked responses
@@ -190,7 +181,6 @@
     noise_cov=cov_path,
     n_time_points=5,
 )
-report.save("qc_report_5.html", **save_kwargs)
 
 
 # %%
@@ -234,7 +224,6 @@
     eog_scores=eog_scores,
     title="ICA components (artifact inspection)",
 )
-report.save("qc_report_6.html", **save_kwargs)
 
 # %%
 # MEG–MRI coregistration
@@ -253,7 +242,6 @@
     subject=subject,
     subjects_dir=subjects_dir,
 )
-report.save("qc_report_7.html", **save_kwargs)
 
 # %%
 # MRI and BEM surfaces
@@ -270,4 +258,10 @@
     title="BEM surfaces",
     decim=20,  # for speed
 )
-report.save("qc_report_8.html", **save_kwargs)
+
+# %%
+# View the final report
+# ---------------------
+# You can set ``open_browser=True`` to have it pop open a browser tab if you want:
+
+report.save("qc_report.html", overwrite=True, open_browser=False)
