code: def run_tutorials(
      repo_dir: str,
      include_ignored: bool = False,
      smoke_test: bool = False,
      name: Optional[str] = None,
  ) -> None:
      """
      Run each tutorial, print statements on how it ran, and write a data set as a csv
      to a directory.
      """
      mode = "smoke test" if smoke_test else "standard"
      results_already_stored = (
          elt
          for elt in os.listdir()
          if elt[-4:] == ".csv"
          and elt.split("_")[0] in ("smoke-test", "standard")
      )
      for fname in results_already_stored:
          raise RuntimeError(
              f"There are already tutorial results files stored, such as {fname}. "
              "This is not allowed because GitHub Actions will look for all "
              "tutorial results files and write them to the 'artifacts' branch. "
              "Please remove all files matching pattern "
              "'standard_*.csv' or 'smoke-test_*.csv' in the current directory."
          )
      print(f"Running tutorial(s) in {mode} mode.")
      if not smoke_test:
          print("This may take a long time...")
      tutorial_dir = Path(repo_dir).joinpath("tutorials")
      num_runs = 0
      num_errors = 0
      ignored_tutorials = (
          IGNORE_ALWAYS
          if smoke_test
          else IGNORE_ALWAYS | RUN_IF_SMOKE_TEST_IGNORE_IF_STANDARD
      )
  
      tutorials = sorted(
          t
          for t in tutorial_dir.iterdir()
          if t.is_file and t.suffix == ".ipynb"
      )
      if name is not None:
          tutorials = [t for t in tutorials if t.name == name]
          if len(tutorials) == 0:
              raise RuntimeError(
                  f"Specified tutorial {name} not found in directory."
              )
  
      df = pd.DataFrame(
          {
              "name": [t.name for t in tutorials],
              "ran_successfully": False,
              "runtime": float("nan"),
              "start_mem": float("nan"),
              "max_mem": float("nan"),
          }
      ).set_index("name")
  
      for tutorial in tutorials:
          if not include_ignored and tutorial.name in ignored_tutorials:
              print(f"Ignoring tutorial {tutorial.name}.")
              continue
          num_runs += 1
          error, performance_info = run_tutorial(
              tutorial, smoke_test=smoke_test
          )
          if error:
              num_errors += 1
              print(error)
          else:
              print(
                  f"Running tutorial {tutorial.name} took "
                  f"{performance_info['runtime']:.2f} seconds. Memory usage "
                  f"started at {performance_info['start_mem']} MB and the maximum"
                  f" was {performance_info['max_mem']} MB."
              )
              df.loc[tutorial.name, "ran_successfully"] = True
              for k in ["runtime", "start_mem", "max_mem"]:
                  df.loc[tutorial.name, k] = performance_info[k]
  
      if num_errors > 0:
          raise RuntimeError(
              f"Running {num_runs} tutorials resulted in {num_errors} errors."
          )
  
      fname = get_output_file_path(smoke_test=smoke_test)
      print(f"Writing report to {fname}.")
      df.to_csv(fname)
  
file_path: botorch/scripts/run_tutorials.py
imports: from __future__ import annotations
  import argparse
  import datetime
  import os
  import subprocess
  import time
  from pathlib import Path
  from subprocess import CalledProcessError
  from typing import Any, Dict, Optional, Tuple
  import pandas
  from memory_profiler import memory_usage
label_desc: Use image node_id 6 for calling a global function with example usage: run_tutorials(repo_dir, include_ignored, smoke_test, name) without return types