Repository: sktime/sktime
Pull request #8148 (2025-04-04 23:37:21)

[MNT] 0.37.0 deprecations and change actions
Carries out deprecations and change actions scheduled for 0.35.0:

* remove deprecated `annotation` module and `BaseAnnotator` - replaced by `detection` module and `BaseDetector`
* remove deprecated `Y` argument in `BaseDetector` methods
* remove deprecated `HierarchyEnsembleForecaster.fitted_list` parameter
* bump deprecation/change checks scheduled for 0.37.0 to 0.38.0

review-notebook-app[bot]: Check out this pull request on&nbsp; <a href="https://app.reviewnb.com/sktime/sktime/pull/8148"><img align="absmiddle"  alt="ReviewNB" height="28" class="BotMessageButtonImage" src="https://raw.githubusercontent.com/ReviewNB/support/master/images/button_reviewnb.png"/></a> 

 See visual diffs & provide feedback on Jupyter Notebooks. 

---

 <i>Powered by <a href='https://www.reviewnb.com/?utm_source=gh'>ReviewNB</a></i>

Patch:
diff --git a/docs/source/get_started.rst b/docs/source/get_started.rst
index 7aabb7648..e7aa2d65f 100644
--- a/docs/source/get_started.rst
+++ b/docs/source/get_started.rst
@@ -151,7 +151,7 @@ Time Series Annotation
 
 .. code-block:: python
 
-    >>> from sktime.annotation.adapters import PyODAnnotator
+    >>> from sktime.detection.adapters import PyODAnnotator
     >>> from pyod.models.iforest import IForest
     >>> from sktime.datasets import load_airline
     >>> y = load_airline()
diff --git a/examples/annotation/segmentation_with_clasp.ipynb b/examples/annotation/segmentation_with_clasp.ipynb
index 20c2d1c23..94eda56fe 100644
--- a/examples/annotation/segmentation_with_clasp.ipynb
+++ b/examples/annotation/segmentation_with_clasp.ipynb
@@ -31,7 +31,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 1,
+   "execution_count": null,
    "id": "religious-fields",
    "metadata": {},
    "outputs": [],
@@ -46,12 +46,12 @@
     "sns.set_theme()\n",
     "sns.set_color_codes()\n",
     "\n",
-    "from sktime.annotation.clasp import ClaSPSegmentation, find_dominant_window_sizes\n",
-    "from sktime.annotation.plotting.utils import (\n",
+    "from sktime.datasets import load_electric_devices_segmentation\n",
+    "from sktime.detection.clasp import ClaSPSegmentation, find_dominant_window_sizes\n",
+    "from sktime.detection.plotting.utils import (\n",
     "    plot_time_series_with_change_points,\n",
     "    plot_time_series_with_profiles,\n",
-    ")\n",
-    "from sktime.datasets import load_electric_devices_segmentation"
+    ")"
    ]
   },
   {
diff --git a/pyproject.toml b/pyproject.toml
index f502a7a1a..e05dd44d7 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -158,7 +158,6 @@ all_extras_pandas2 = [
   'tbats>=1.1; python_version < "3.12"',
   'temporian<0.9.0,>=0.7.0,!=0.8.0; python_version < "3.12" and sys_platform != "win32" and platform_machine != "aarch64"' ,
   'tensorflow<2.20,>=2; python_version < "3.13"',
-  'tsbootstrap<0.2,>=0.1.0; python_version < "3.13"',
   'tsfresh>=0.17; python_version < "3.12"',
   'tslearn<0.7.0,!=0.6.0,>=0.5.2; python_version < "3.11"',
   'u8darts>=0.29.0,<0.32.0; python_version < "3.13"',
diff --git a/sktime/annotation/__init__.py b/sktime/annotation/__init__.py
deleted file mode 100644
index c39a804f9..000000000
--- a/sktime/annotation/__init__.py
+++ /dev/null
@@ -1,1 +0,0 @@
-"""Time series anomaly, changepoint detection, segmentation."""
diff --git a/sktime/annotation/adapters/__init__.py b/sktime/annotation/adapters/__init__.py
deleted file mode 100644
index 687324398..000000000
--- a/sktime/annotation/adapters/__init__.py
+++ /dev/null
@@ -1,7 +0,0 @@
-#!/usr/bin/env python3 -u
-# copyright: sktime developers, BSD-3-Clause License (see LICENSE file)
-"""Implements adapters for time series annotation."""
-
-__all__ = ["PyODAnnotator"]
-
-from sktime.detection.adapters._pyod import PyODAnnotator
diff --git a/sktime/annotation/base/__init__.py b/sktime/annotation/base/__init__.py
deleted file mode 100644
index 3e1f6ec31..000000000
--- a/sktime/annotation/base/__init__.py
+++ /dev/null
@@ -1,7 +0,0 @@
-#!/usr/bin/env python3 -u
-# copyright: sktime developers, BSD-3-Clause License (see LICENSE file)
-"""Implements base classes for annotation in sktime."""
-
-__all__ = ["BaseSeriesAnnotator"]
-
-from sktime.detection.base._base import BaseSeriesAnnotator
diff --git a/sktime/annotation/bs.py b/sktime/annotation/bs.py
deleted file mode 100644
index 16b5ec687..000000000
--- a/sktime/annotation/bs.py
+++ /dev/null
@@ -1,5 +0,0 @@
-"""Binary segmentation annotator for change point detection."""
-
-from sktime.detection.bs import BinarySegmentation
-
-__all__ = ["BinarySegmentation"]
diff --git a/sktime/annotation/clasp.py b/sktime/annotation/clasp.py
deleted file mode 100644
index e5153cfbd..000000000
--- a/sktime/annotation/clasp.py
+++ /dev/null
@@ -1,17 +0,0 @@
-"""ClaSP (Classification Score Profile) Segmentation.
-
-Notes
------
-As described in
-@inproceedings{clasp2021,
-  title={ClaSP - Time Series Segmentation},
-  author={Sch"afer, Patrick and Ermshaus, Arik and Leser, Ulf},
-  booktitle={CIKM},
-  year={2021}
-}
-"""
-
-from sktime.detection.clasp import ClaSPSegmentation, find_dominant_window_sizes
-
-__author__ = ["ermshaua", "patrickzib"]
-__all__ = ["ClaSPSegmentation", "find_dominant_window_sizes"]
diff --git a/sktime/annotation/clust.py b/sktime/annotation/clust.py
deleted file mode 100644
index e089312b2..000000000
--- a/sktime/annotation/clust.py
+++ /dev/null
@@ -1,10 +0,0 @@
-"""Cluster Segmentation.
-
-Implementing segmentation using clustering, Read more at
-<https://en.wikipedia.org/wiki/Cluster_analysis>_.
-"""
-
-from sktime.detection.clust import ClusterSegmenter
-
-__author__ = ["Ankit-1204"]
-__all__ = ["ClusterSegmenter"]
diff --git a/sktime/annotation/compose/__init__.py b/sktime/annotation/compose/__init__.py
deleted file mode 100644
index e497aa2a0..000000000
--- a/sktime/annotation/compose/__init__.py
+++ /dev/null
@@ -1,10 +0,0 @@
-"""Composition for outlier, changepoint, segmentation estimators."""
-
-# copyright: sktime developers, BSD-3-Clause License (see LICENSE file)
-
-from sktime.detection.compose import AnnotatorAsTransformer, AnnotatorPipeline
-
-__all__ = [
-    "AnnotatorAsTransformer",
-    "AnnotatorPipeline",
-]
diff --git a/sktime/annotation/datagen.py b/sktime/annotation/datagen.py
deleted file mode 100644
index 1205d1193..000000000
--- a/sktime/annotation/datagen.py
+++ /dev/null
@@ -1,21 +0,0 @@
-"""Synthetic data generating functions."""
-
-from sktime.detection.datagen import (
-    GenBasicGauss,
-    label_piecewise_normal,
-    labels_with_repeats,
-    piecewise_multinomial,
-    piecewise_normal,
-    piecewise_normal_multivariate,
-    piecewise_poisson,
-)
-
-__all__ = [
-    "GenBasicGauss",
-    "label_piecewise_normal",
-    "labels_with_repeats",
-    "piecewise_multinomial",
-    "piecewise_normal",
-    "piecewise_normal_multivariate",
-    "piecewise_poisson",
-]
diff --git a/sktime/annotation/eagglo.py b/sktime/annotation/eagglo.py
deleted file mode 100644
index 947afddeb..000000000
--- a/sktime/annotation/eagglo.py
+++ /dev/null
@@ -1,6 +0,0 @@
-"""E-Agglo: agglomerative clustering algorithm that preserves observation order."""
-
-from sktime.detection.eagglo import EAgglo
-
-__author__ = ["KatieBuc"]
-__all__ = ["EAgglo"]
diff --git a/sktime/annotation/ggs.py b/sktime/annotation/ggs.py
deleted file mode 100644
index 961a656df..000000000
--- a/sktime/annotation/ggs.py
+++ /dev/null
@@ -1,37 +0,0 @@
-"""Greedy Gaussian Segmentation (GGS).
-
-The method approximates solutions for the problem of breaking a
-multivariate time series into segments, where the data in each segment
-could be modeled as independent samples from a multivariate Gaussian
-distribution. It uses a dynamic programming search algorithm with
-a heuristic that allows finding approximate solution in linear time with
-respect to the data length and always yields locally optimal choice.
-
-This module is structured with the ``GGS`` that implements the actual
-segmentation algorithm and a ``GreedyGaussianSegmentation`` that
-interfaces the algorithm with the sklearn/sktime api. The benefit
-behind that design is looser coupling between the logic and the
-interface introduced to allow for easier changes of either part
-since segmentation still has an experimental nature. When making
-algorithm changes you probably want to look into ``GGS`` when
-evolving the sktime/sklearn interface look into ``GreedyGaussianSegmentation``.
-This design also allows adapting ``GGS`` to other interfaces.
-
-Notes
------
-Based on the work from [1]_.
-
-- source code adapted based on: https://github.com/cvxgrp/GGS
-- paper available at: https://stanford.edu/~boyd/papers/pdf/ggs.pdf
-
-References
-----------
-.. [1] Hallac, D., Nystrup, P. & Boyd, S.
-   "Greedy Gaussian segmentation of multivariate time series.",
-    Adv Data Anal Classif 13, 727-751 (2019).
-    https://doi.org/10.1007/s11634-018-0335-0
-"""
-
-from sktime.detection.ggs import GreedyGaussianSegmentation
-
-__all__ = ["GreedyGaussianSegmentation"]
diff --git a/sktime/annotation/hmm.py b/sktime/annotation/hmm.py
deleted file mode 100644
index 13e9ecdbd..000000000
--- a/sktime/annotation/hmm.py
+++ /dev/null
@@ -1,11 +0,0 @@
-"""HMM Annotation Estimator.
-
-Implements a basic Hidden Markov Model (HMM) as an annotation estimator. To read more
-about the algorithm, check out the `HMM wikipedia page
-<https://en.wikipedia.org/wiki/Hidden_Markov_model>`_.
-"""
-
-from sktime.detection.hmm import HMM
-
-__author__ = ["miraep8"]
-__all__ = ["HMM"]
diff --git a/sktime/annotation/hmm_learn/__init__.py b/sktime/annotation/hmm_learn/__init__.py
deleted file mode 100644
index 327e61908..000000000
--- a/sktime/annotation/hmm_learn/__init__.py
+++ /dev/null
@@ -1,10 +0,0 @@
-# !/usr/bin/env python3 -u
-# copyright: sktime developers, BSD-3-Clause License (see LICENSE file)
-"""Implements wrappers for estimators from hmmlearn."""
-
-__all__ = ["BaseHMMLearn", "GaussianHMM", "GMMHMM", "PoissonHMM"]
-
-from sktime.detection.hmm_learn.base import BaseHMMLearn
-from sktime.detection.hmm_learn.gaussian import GaussianHMM
-from sktime.detection.hmm_learn.gmm import GMMHMM
-from sktime.detection.hmm_learn.poisson import PoissonHMM
diff --git a/sktime/annotation/hmm_learn/base.py b/sktime/annotation/hmm_learn/base.py
deleted file mode 100644
index 156c19537..000000000
--- a/sktime/annotation/hmm_learn/base.py
+++ /dev/null
@@ -1,13 +0,0 @@
-"""Hidden Markov Model based annotation from hmmlearn.
-
-This code provides a base interface template for models
-from hmmlearn for using that library for annotation of time series.
-
-Please see the original library
-(https://github.com/hmmlearn/hmmlearn/blob/main/lib/hmmlearn/hmm.py)
-"""
-
-from sktime.detection.hmm_learn.base import BaseHMMLearn
-
-__author__ = ["miraep8"]
-__all__ = ["BaseHMMLearn"]
diff --git a/sktime/annotation/hmm_learn/gaussian.py b/sktime/annotation/hmm_learn/gaussian.py
deleted file mode 100644
index 066f94164..000000000
--- a/sktime/annotation/hmm_learn/gaussian.py
+++ /dev/null
@@ -1,10 +0,0 @@
-"""Hidden Markov Model with Gaussian emissions.
-
-Please see the original library
-(https://github.com/hmmlearn/hmmlearn/blob/main/lib/hmmlearn/hmm.py)
-"""
-
-from sktime.detection.hmm_learn.gaussian import GaussianHMM
-
-__author__ = ["miraep8"]
-__all__ = ["GaussianHMM"]
diff --git a/sktime/annotation/hmm_learn/gmm.py b/sktime/annotation/hmm_learn/gmm.py
deleted file mode 100644
index 86e30b94d..000000000
--- a/sktime/annotation/hmm_learn/gmm.py
+++ /dev/null
@@ -1,10 +0,0 @@
-"""Hidden Markov Model with Gaussian mixture emissions.
-
-Please see the original library
-(https://github.com/hmmlearn/hmmlearn/blob/main/lib/hmmlearn/hmm.py)
-"""
-
-from sktime.detection.hmm_learn.gmm import GMMHMM
-
-__author__ = ["miraep8"]
-__all__ = ["GMMHMM"]
diff --git a/sktime/annotation/hmm_learn/poisson.py b/sktime/annotation/hmm_learn/poisson.py
deleted file mode 100644
index e5f73929f..000000000
--- a/sktime/annotation/hmm_learn/poisson.py
+++ /dev/null
@@ -1,10 +0,0 @@
-"""Hidden Markov Model with Poisson emissions.
-
-Please see the original library
-(https://github.com/hmmlearn/hmmlearn/blob/main/lib/hmmlearn/hmm.py)
-"""
-
-from sktime.detection.hmm_learn.poisson import PoissonHMM
-
-__author__ = ["klam-data", "pyyim", "mgorlin"]
-__all__ = ["PoissonHMM"]
diff --git a/sktime/annotation/igts.py b/sktime/annotation/igts.py
deleted file mode 100644
index 494e5acc5..000000000
--- a/sktime/annotation/igts.py
+++ /dev/null
@@ -1,21 +0,0 @@
-"""Information Gain-based Temporal Segmentation.
-
-Information Gain Temporal Segmentation (IGTS) is a method for segmenting
-multivariate time series based off reducing the entropy in each segment [1]_.
-
-The amount of entropy lost by the segmentations made is called the Information
-Gain (IG). The aim is to find the segmentations that have the maximum information
-gain for any number of segmentations.
-
-References
-----------
-.. [1] Sadri, Amin, Yongli Ren, and Flora D. Salim.
-    "Information gain-based metric for recognizing transitions in human activities.",
-    Pervasive and Mobile Computing, 38, 92-109, (2017).
-    https://www.sciencedirect.com/science/article/abs/pii/S1574119217300081
-"""
-
-from sktime.detection.igts import InformationGainSegmentation
-
-__all__ = ["InformationGainSegmentation"]
-__author__ = ["lmmentel"]
diff --git a/sktime/annotation/lof.py b/sktime/annotation/lof.py
deleted file mode 100644
index 61cb2eadd..000000000
--- a/sktime/annotation/lof.py
+++ /dev/null
@@ -1,6 +0,0 @@
-"""Windowed local outlier factor."""
-
-__author__ = ["Alex-JG3"]
-__all__ = ["SubLOF"]
-
-from sktime.detection.lof import SubLOF
diff --git a/sktime/annotation/plotting/__init__.py b/sktime/annotation/plotting/__init__.py
deleted file mode 100644
index 87aafb282..000000000
--- a/sktime/annotation/plotting/__init__.py
+++ /dev/null
@@ -1,3 +0,0 @@
-#!/usr/bin/env python3 -u
-# copyright: sktime developers, BSD-3-Clause License (see LICENSE file)
-"""Implements base classes for plotting in sktime."""
diff --git a/sktime/annotation/plotting/utils.py b/sktime/annotation/plotting/utils.py
deleted file mode 100644
index e9a24ce01..000000000
--- a/sktime/annotation/plotting/utils.py
+++ /dev/null
@@ -1,13 +0,0 @@
-#!/usr/bin/env python3 -u
-# copyright: sktime developers, BSD-3-Clause License (see LICENSE file)
-"""Utility class for plotting functionality."""
-
-from sktime.detection.plotting.utils import (
-    plot_time_series_with_change_points,
-    plot_time_series_with_profiles,
-)
-
-__all__ = [
-    "plot_time_series_with_change_points",
-    "plot_time_series_with_profiles",
-]
diff --git a/sktime/annotation/stray.py b/sktime/annotation/stray.py
deleted file mode 100644
index 5e2b0cbd6..000000000
--- a/sktime/annotation/stray.py
+++ /dev/null
@@ -1,6 +0,0 @@
-"""Tests for STRAY (Search TRace AnomalY) outlier estimator."""
-
-from sktime.detection.stray import STRAY
-
-__author__ = ["KatieBuc"]
-__all__ = ["STRAY"]
diff --git a/sktime/classification/early_classification/_probability_threshold.py b/sktime/classification/early_classification/_probability_threshold.py
index 324873333..eb7b0ceb1 100644
--- a/sktime/classification/early_classification/_probability_threshold.py
+++ b/sktime/classification/early_classification/_probability_threshold.py
@@ -20,7 +20,7 @@ from sktime.classification.interval_based import CanonicalIntervalForest
 from sktime.utils.validation.panel import check_X
 
 
-# TODO: fix this in 0.37.0
+# TODO: fix this in 0.38.0
 # base class should have been changed to BaseEarlyClassifier
 class ProbabilityThresholdEarlyClassifier(BaseClassifier):
     """Probability Threshold Early Classifier.
diff --git a/sktime/datatypes/__init__.py b/sktime/datatypes/__init__.py
index acc6a3e34..9281f4805 100644
--- a/sktime/datatypes/__init__.py
+++ b/sktime/datatypes/__init__.py
@@ -11,15 +11,11 @@ from sktime.datatypes._check import (
 from sktime.datatypes._convert import convert, convert_to
 from sktime.datatypes._examples import get_examples
 from sktime.datatypes._registry import (
-    ALL_TIME_SERIES_MTYPES,
-    MTYPE_LIST_HIERARCHICAL,
-    MTYPE_LIST_PANEL,
-    MTYPE_LIST_PROBA,
-    MTYPE_LIST_SERIES,
-    MTYPE_LIST_TABLE,
-    MTYPE_REGISTER,
+    AMBIGUOUS_MTYPES,
     SCITYPE_LIST,
     SCITYPE_REGISTER,
+    generate_mtype_list,
+    generate_mtype_register,
     mtype_to_scitype,
     scitype_to_mtype,
 )
@@ -51,3 +47,29 @@ __all__ = [
     "update_data",
     "VectorizedDF",
 ]
+
+
+def __getattr__(name):
+    getter_dict = {
+        "MTYPE_LIST_ALIGNMENT": "Alignment",
+        "MTYPE_LIST_HIERARCHICAL": "Hierarchical",
+        "MTYPE_LIST_PANEL": "Panel",
+        "MTYPE_LIST_PROBA": "Proba",
+        "MTYPE_LIST_SERIES": "Series",
+        "MTYPE_LIST_TABLE": "Table",
+    }
+    if name in getter_dict:
+        return generate_mtype_list(scitype=getter_dict[name])
+
+    if name == "MTYPE_REGISTER":
+        return generate_mtype_register()
+
+    if name == "ALL_TIME_SERIES_MTYPES":
+        series = generate_mtype_list(scitype="Series")
+        panel = generate_mtype_list(scitype="Panel")
+        hierarchical = generate_mtype_list(scitype="Hierarchical")
+        all_tsm = series + panel + hierarchical
+        ALL_TIME_SERIES_MTYPES = list(set(all_tsm).difference(AMBIGUOUS_MTYPES))
+        return ALL_TIME_SERIES_MTYPES
+
+    raise AttributeError(f"module {__name__} has no attribute {name}")
diff --git a/sktime/datatypes/_alignment/__init__.py b/sktime/datatypes/_alignment/__init__.py
index bedd16709..64a925efa 100644
--- a/sktime/datatypes/_alignment/__init__.py
+++ b/sktime/datatypes/_alignment/__init__.py
@@ -1,11 +1,1 @@
-"""Module exports: Alignment type checkers and mtype inference."""
-
-from sktime.datatypes._alignment._registry import (
-    MTYPE_LIST_ALIGNMENT,
-    MTYPE_REGISTER_ALIGNMENT,
-)
-
-__all__ = [
-    "MTYPE_LIST_ALIGNMENT",
-    "MTYPE_REGISTER_ALIGNMENT",
-]
+"""Module: Alignment type checkers and mtype inference."""
diff --git a/sktime/datatypes/_alignment/_check.py b/sktime/datatypes/_alignment/_check.py
index b8044e32a..e86e5a460 100644
--- a/sktime/datatypes/_alignment/_check.py
+++ b/sktime/datatypes/_alignment/_check.py
@@ -155,6 +155,7 @@ class AlignmentIloc(ScitypeAlignment):
         "name": "alignment",  # any string
         "name_python": "alignment_iloc",  # lower_snake_case
         "name_aliases": [],
+        "description": "alignment in pd.DataFrame format, values are iloc index references",  # noqa: E501
         "python_version": None,
         "python_dependencies": "pandas",
     }
@@ -223,6 +224,7 @@ class AlignmentLoc(ScitypeAlignment):
         "name": "alignment_loc",  # any string
         "name_python": "alignment_loc",  # lower_snake_case
         "name_aliases": [],
+        "description": "alignment in pd.DataFrame format, values are loc index references",  # noqa: E501
         "python_version": None,
         "python_dependencies": "pandas",
     }
diff --git a/sktime/datatypes/_alignment/_registry.py b/sktime/datatypes/_alignment/_registry.py
deleted file mode 100644
index ae5c9cd57..000000000
--- a/sktime/datatypes/_alignment/_registry.py
+++ /dev/null
@@ -1,25 +0,0 @@
-"""Registry of mtypes for Alignment scitype.
-
-See datatypes._registry for API.
-"""
-
-__all__ = [
-    "MTYPE_REGISTER_ALIGNMENT",
-    "MTYPE_LIST_ALIGNMENT",
-]
-
-
-MTYPE_REGISTER_ALIGNMENT = [
-    (
-        "alignment",
-        "Alignment",
-        "pd.DataFrame in alignment format, values are iloc index references",
-    ),
-    (
-        "alignment_loc",
-        "Alignment",
-        "pd.DataFrame in alignment format, values are loc index references",
-    ),
-]
-
-MTYPE_LIST_ALIGNMENT = [x[0] for x in MTYPE_REGISTER_ALIGNMENT]
diff --git a/sktime/datatypes/_base/_base.py b/sktime/datatypes/_base/_base.py
index 9a48f4501..608efb5d5 100644
--- a/sktime/datatypes/_base/_base.py
+++ b/sktime/datatypes/_base/_base.py
@@ -24,6 +24,8 @@ class BaseDatatype(BaseObject):
         "python_version": None,
         "python_dependencies": None,
         "python_type": "object",  # implied python type (lowest)
+        "internal_only": False,  # whether type is for internal use only
+        "skip_in_checks": False,  # whether to skip in inference checks (check_dict)
     }
 
     def __init__(self):
diff --git a/sktime/datatypes/_check.py b/sktime/datatypes/_check.py
index 79657c67d..f8ca8de89 100644
--- a/sktime/datatypes/_check.py
+++ b/sktime/datatypes/_check.py
@@ -27,9 +27,13 @@ from functools import lru_cache
 
 import numpy as np
 
-from sktime.datatypes._base import BaseDatatype
 from sktime.datatypes._base._common import _metadata_requested, _ret
-from sktime.datatypes._registry import AMBIGUOUS_MTYPES, SCITYPE_LIST, mtype_to_scitype
+from sktime.datatypes._registry import (
+    AMBIGUOUS_MTYPES,
+    SCITYPE_LIST,
+    generate_mtype_cls_list,
+    mtype_to_scitype,
+)
 
 
 def get_check_dict(soft_deps="present"):
@@ -43,6 +47,12 @@ def get_check_dict(soft_deps="present"):
     soft_deps : str, optional - one of "present", "all"
         "present" - only checks with soft dependencies present are included
         "all" - all checks are included
+
+    Returns
+    -------
+    check_dict : dict of (str, str) : object (mtype registry class)
+        dictionary of check classes, with keys being tuples of (mtype, scitype)
+        and values an instance of the check class for that mtype/scitype combination
     """
     if soft_deps not in ["present", "all"]:
         raise ValueError(
@@ -56,25 +66,14 @@ def get_check_dict(soft_deps="present"):
 @lru_cache(maxsize=1)
 def generate_check_dict(soft_deps="present"):
     """Generate check_dict using lookup."""
-    from skbase.utils.dependencies import _check_estimator_deps
-
-    from sktime.utils.retrieval import _all_classes
-
-    classes = _all_classes("sktime.datatypes")
-    classes = [x[1] for x in classes]
-    classes = [x for x in classes if issubclass(x, BaseDatatype)]
-    classes = [x for x in classes if not x.__name__.startswith("Base")]
-    classes = [x for x in classes if not x.__name__.startswith("Scitype")]
-
-    # subset only to data types with soft dependencies present
-    if soft_deps == "present":
-        classes = [x for x in classes if _check_estimator_deps(x, severity="none")]
+    classes = generate_mtype_cls_list(soft_deps=soft_deps)
 
     check_dict = dict()
     for cls in classes:
         k = cls()
-        key = k._get_key()
-        check_dict[key] = k
+        if not k.get_tag("skip_in_checks", False):
+            key = k._get_key()
+            check_dict[key] = k
 
     return check_dict
 
diff --git a/sktime/datatypes/_hierarchical/__init__.py b/sktime/datatypes/_hierarchical/__init__.py
index d262e59f0..42feed418 100644
--- a/sktime/datatypes/_hierarchical/__init__.py
+++ b/sktime/datatypes/_hierarchical/__init__.py
@@ -3,13 +3,5 @@
 from sktime.datatypes._hierarchical._convert import (
     convert_dict as convert_dict_Hierarchical,
 )
-from sktime.datatypes._hierarchical._registry import (
-    MTYPE_LIST_HIERARCHICAL,
-    MTYPE_REGISTER_HIERARCHICAL,
-)
 
-__all__ = [
-    "convert_dict_Hierarchical",
-    "MTYPE_LIST_HIERARCHICAL",
-    "MTYPE_REGISTER_HIERARCHICAL",
-]
+__all__ = ["convert_dict_Hierarchical"]
diff --git a/sktime/datatypes/_hierarchical/_check.py b/sktime/datatypes/_hierarchical/_check.py
index dfedfbadb..e6086e064 100644
--- a/sktime/datatypes/_hierarchical/_check.py
+++ b/sktime/datatypes/_hierarchical/_check.py
@@ -143,6 +143,7 @@ class HierarchicalPdMultiIndex(ScitypeHierarchical):
         "name": "pd_multiindex_hier",  # any string
         "name_python": "hier_pd_df",  # lower_snake_case
         "name_aliases": [],
+        "description": "pandas.DataFrame with hierarchical MultiIndex",
         "python_version": None,
         "python_dependencies": "pandas",
         "python_type": "pandas.DataFrame",
@@ -264,6 +265,7 @@ class HierarchicalDask(ScitypeHierarchical):
         "name": "dask_hierarchical",  # any string
         "name_python": "hier_dask",  # lower_snake_case
         "name_aliases": [],
+        "description": "dask frame with multiple hierarchical indices, as per dask_to_pd convention",  # noqa: E501
         "python_version": None,
         "python_dependencies": "dask",
         "python_type": "dask.dataframe",
@@ -345,6 +347,7 @@ class HierarchicalPolarsEager(ScitypeHierarchical):
         "name": "polars_hierarchical",  # any string
         "name_python": "hier_polars_eager",  # lower_snake_case
         "name_aliases": [],
+        "description": "polars frame with multiple hierarchical indices, as per polars_to_pd convention",  # noqa: E501
         "python_version": None,
         "python_dependencies": "polars",
         "python_type": "polars.DataFrame",
diff --git a/sktime/datatypes/_hierarchical/_convert.py b/sktime/datatypes/_hierarchical/_convert.py
index 308cf9f25..1951cc2bd 100644
--- a/sktime/datatypes/_hierarchical/_convert.py
+++ b/sktime/datatypes/_hierarchical/_convert.py
@@ -4,9 +4,15 @@ __all__ = [
 
 from sktime.datatypes._convert_utils._coerce import _coerce_df_dtypes
 from sktime.datatypes._convert_utils._convert import _extend_conversions
-from sktime.datatypes._hierarchical._registry import MTYPE_LIST_HIERARCHICAL
 from sktime.utils.dependencies import _check_soft_dependencies
 
+# this needs to be refactored with the convert module
+MTYPE_LIST_HIERARCHICAL = [
+    "pd_multiindex_hier",
+    "dask_hierarchical",
+    "polars_hierarchical",
+]
+
 # dictionary indexed by triples of types
 #  1st element = convert from - type
 #  2nd element = convert to - type
diff --git a/sktime/datatypes/_hierarchical/_registry.py b/sktime/datatypes/_hierarchical/_registry.py
deleted file mode 100644
index 81882ba67..000000000
--- a/sktime/datatypes/_hierarchical/_registry.py
+++ /dev/null
@@ -1,37 +0,0 @@
-"""Registry of mtypes for Hierarchical scitype.
-
-See datatypes._registry for API.
-"""
-
-__all__ = [
-    "MTYPE_REGISTER_HIERARCHICAL",
-    "MTYPE_LIST_HIERARCHICAL",
-    "MTYPE_SOFT_DEPS_HIERARCHICAL",
-]
-
-
-MTYPE_REGISTER_HIERARCHICAL = [
-    (
-        "pd_multiindex_hier",
-        "Hierarchical",
-        "pd.DataFrame with MultiIndex",
-    ),
-    (
-        "dask_hierarchical",
-        "Hierarchical",
-        "dask frame with multiple hierarchical indices, as per dask_to_pd convention",
-    ),
-    (
-        "polars_hierarchical",
-        "Hierarchical",
-        "polars frame with multiple hierarchical indices, "
-        "as per polars_to_pd convention",
-    ),
-]
-
-MTYPE_SOFT_DEPS_HIERARCHICAL = {
-    "dask_hierarchical": "dask",
-    "polars_hierarchical": "polars",
-}
-
-MTYPE_LIST_HIERARCHICAL = [x[0] for x in MTYPE_REGISTER_HIERARCHICAL]
diff --git a/sktime/datatypes/_panel/__init__.py b/sktime/datatypes/_panel/__init__.py
index 6fc3dfe94..b582c5f46 100644
--- a/sktime/datatypes/_panel/__init__.py
+++ b/sktime/datatypes/_panel/__init__.py
@@ -1,10 +1,5 @@
 """Module exports: Panel type checkers, converters and mtype inference."""
 
 from sktime.datatypes._panel._convert import convert_dict as convert_dict_Panel
-from sktime.datatypes._panel._registry import MTYPE_LIST_PANEL, MTYPE_REGISTER_PANEL
 
-__all__ = [
-    "convert_dict_Panel",
-    "MTYPE_LIST_PANEL",
-    "MTYPE_REGISTER_PANEL",
-]
+__all__ = ["convert_dict_Panel"]
diff --git a/sktime/datatypes/_panel/_check.py b/sktime/datatypes/_panel/_check.py
index e05a9a774..6b642939d 100644
--- a/sktime/datatypes/_panel/_check.py
+++ b/sktime/datatypes/_panel/_check.py
@@ -156,6 +156,7 @@ class PanelDfList(ScitypePanel):
         "name": "df-list",  # any string
         "name_python": "panel_df_list",  # lower_snake_case
         "name_aliases": [],
+        "description": "list of pd.DataFrame",
         "python_version": None,
         "python_dependencies": "pandas",
         "python_type": "list",
@@ -318,6 +319,7 @@ class PanelNp3D(ScitypePanel):
         "name": "numpy3D",  # any string
         "name_python": "panel_np_3d",  # lower_snake_case
         "name_aliases": [],
+        "description": "3D np.array of format (n_instances, n_columns, n_timepoints)",
         "python_version": None,
         "python_dependencies": "numpy",
         "python_type": "numpy.ndarray",
@@ -474,6 +476,7 @@ class PanelPdMultiIndex(ScitypePanel):
         "name": "pd-multiindex",  # any string
         "name_python": "panel_pd_df",  # lower_snake_case
         "name_aliases": [],
+        "description": "pd.DataFrame with multi-index (instances, timepoints)",
         "python_version": None,
         "python_dependencies": "pandas",
         "python_type": "pandas.DataFrame",
@@ -746,6 +749,7 @@ class PanelNestedDf(ScitypePanel):
         "name": "nested_univ",  # any string
         "name_python": "panel_pd_nested",  # lower_snake_case
         "name_aliases": [],
+        "description": "pd.DataFrame with one column per variable, pd.Series in cells",
         "python_version": None,
         "python_dependencies": "pandas",
         "python_type": "pandas.DataFrame",
@@ -895,12 +899,17 @@ class PanelNumpyFlat(ScitypePanel):
         "name": "numpyflat",  # any string
         "name_python": "panel_np_flat",  # lower_snake_case
         "name_aliases": [],
+        "description": (
+            "WARNING: only for internal use, not a fully supported Panel mtype. "
+            "2D np.array of format (n_instances, n_columns*n_timepoints)"
+        ),
         "python_version": None,
         "python_dependencies": "numpy",
         "python_type": "numpy.ndarray",
         "capability:multivariate": False,
         "capability:unequally_spaced": False,
         "capability:missing_values": True,
+        "internal_only": True,
     }
 
     def _check(self, obj, return_metadata=False, var_name="obj"):
@@ -1009,6 +1018,7 @@ class PanelDask(ScitypePanel):
         "name": "dask_panel",  # any string
         "name_python": "panel_dask",  # lower_snake_case
         "name_aliases": [],
+        "description": "dask DataFrame based panel of time series",
         "python_version": None,
         "python_dependencies": "dask",
         "python_type": "dask.dataframe",
@@ -1084,6 +1094,7 @@ class PanelPolarsEager(ScitypePanel):
         "name": "polars_panel",  # any string
         "name_python": "panel_polars",  # lower_snake_case
         "name_aliases": [],
+        "description": "polars.DataFrame based panel of time series",
         "python_version": None,
         "python_dependencies": "polars",
         "python_type": "polars.DataFrame",
@@ -1277,6 +1288,7 @@ class PanelGluontsList(ScitypePanel):
         "name": "gluonts_ListDataset_panel",  # any string
         "name_python": "panel_gluonts_list",  # lower_snake_case
         "name_aliases": [],
+        "description": "gluonts list based panel of time series",
         "python_version": None,
         "python_dependencies": None,
         "python_type": "list",
@@ -1428,6 +1440,7 @@ class PanelGluontsPandas(ScitypePanel):
         "name": "gluonts_PandasDataset_panel",  # any string
         "name_python": "panel_gluonts_pandas",  # lower_snake_case
         "name_aliases": [],
+        "description": "gluonts PandasDataset based panel of time series",
         "python_version": None,
         "python_dependencies": "gluonts",
         "python_type": "gluonts.PandasDataset",
@@ -1468,8 +1481,10 @@ class PanelGluontsPandas(ScitypePanel):
             return _ret(False, msg, None, return_metadata)
 
         if not hasattr(obj._data_entries.iterable, "iterable"):
-            msg = f"{var_name} must be formed with a multiindex DataFrame to "
-            +"be a valid `pandasDataset_panel`"
+            msg = (
+                f"{var_name} must be formed with a multiindex DataFrame to "
+                "be a valid `pandasDataset_panel`"
+            )
             return _ret(False, msg, None, return_metadata)
 
         # Convert to a pandas DF for easier checks
@@ -1519,3 +1534,153 @@ class PanelGluontsPandas(ScitypePanel):
             metadata["has_nans"] = False
 
         return _ret(True, None, metadata, return_metadata)
+
+
+class PanelPdWide(ScitypePanel):
+    """Data type: panel of time series in pandas wide format.
+
+    Parameters
+    ----------
+    is_univariate: bool
+        True iff table has one variable
+    is_equally_spaced : bool
+        True iff series index is equally spaced
+    is_equal_length: bool
+        True iff all series in panel are of equal length
+    is_empty: bool
+        True iff table has no variables or no instances
+    is_one_series: bool
+        True iff there is only one series in the panel of time series
+    has_nans: bool
+        True iff the table contains NaN values
+    n_instances: int
+        number of instances in the panel of time series
+    n_features: int
+        number of variables in table
+    feature_names: list of int or object
+        names of variables in table
+    dtypekind_dfip: list of DtypeKind enum
+        list of DtypeKind enum values for each feature in the panel,
+        following the data frame interface protocol
+    feature_kind: list of str
+        list of feature kind strings for each feature in the panel,
+        coerced to FLOAT or CATEGORICAL type
+    """
+
+    _tags = {
+        "scitype": "Panel",
+        "name": "pd-wide",  # any string
+        "name_python": "panel_pd_wide",  # lower_snake_case
+        "name_aliases": [],
+        "description": (
+            "WARNING: only for internal use, not a fully supported Panel mtype. "
+            "pd.DataFrame in wide format, cols = (instance*timepoints)"
+        ),
+        "python_version": None,
+        "python_dependencies": "pandas",
+        "python_type": "pandas.DataFrame",
+        "capability:multivariate": False,
+        "capability:unequally_spaced": False,
+        "capability:missing_values": True,
+        "internal_only": True,
+        "skip_in_checks": True,
+    }
+
+    def _check(self, obj, return_metadata=False, var_name="obj"):
+        """Check if obj is of this data type.
+
+        Parameters
+        ----------
+        obj : any
+            Object to check.
+        return_metadata : bool, optional (default=False)
+            Whether to return metadata.
+        var_name : str, optional (default="obj")
+            Name of the variable to check, for use in error messages.
+
+        Returns
+        -------
+        valid : bool
+            Whether obj is of this data type.
+        msg : str, only returned if return_metadata is True.
+            Error message if obj is not of this data type.
+        metadata : dict, only returned if return_metadata is True.
+            Metadata dictionary.
+        """
+        # no checker defined, only used in conversions
+        pass
+
+
+class PanelPdLong(ScitypePanel):
+    """Data type: panel of time series in pandas long format.
+
+    Parameters
+    ----------
+    is_univariate: bool
+        True iff table has one variable
+    is_equally_spaced : bool
+        True iff series index is equally spaced
+    is_equal_length: bool
+        True iff all series in panel are of equal length
+    is_empty: bool
+        True iff table has no variables or no instances
+    is_one_series: bool
+        True iff there is only one series in the panel of time series
+    has_nans: bool
+        True iff the table contains NaN values
+    n_instances: int
+        number of instances in the panel of time series
+    n_features: int
+        number of variables in table
+    feature_names: list of int or object
+        names of variables in table
+    dtypekind_dfip: list of DtypeKind enum
+        list of DtypeKind enum values for each feature in the panel,
+        following the data frame interface protocol
+    feature_kind: list of str
+        list of feature kind strings for each feature in the panel,
+        coerced to FLOAT or CATEGORICAL type
+    """
+
+    _tags = {
+        "scitype": "Panel",
+        "name": "pd-long",  # any string
+        "name_python": "panel_pd_long",  # lower_snake_case
+        "name_aliases": [],
+        "description": (
+            "WARNING: only for internal use, not a fully supported Panel mtype. "
+            "pd.DataFrame in long format, cols = (index, time_index, column)"
+        ),
+        "python_version": None,
+        "python_dependencies": "pandas",
+        "python_type": "pandas.DataFrame",
+        "capability:multivariate": True,
+        "capability:unequally_spaced": True,
+        "capability:missing_values": True,
+        "internal_only": True,
+        "skip_in_checks": True,
+    }
+
+    def _check(self, obj, return_metadata=False, var_name="obj"):
+        """Check if obj is of this data type.
+
+        Parameters
+        ----------
+        obj : any
+            Object to check.
+        return_metadata : bool, optional (default=False)
+            Whether to return metadata.
+        var_name : str, optional (default="obj")
+            Name of the variable to check, for use in error messages.
+
+        Returns
+        -------
+        valid : bool
+            Whether obj is of this data type.
+        msg : str, only returned if return_metadata is True.
+            Error message if obj is not of this data type.
+        metadata : dict, only returned if return_metadata is True.
+            Metadata dictionary.
+        """
+        # no checker defined, only used in conversions
+        pass
diff --git a/sktime/datatypes/_panel/_convert.py b/sktime/datatypes/_panel/_convert.py
index d5283e637..fb2882a99 100644
--- a/sktime/datatypes/_panel/_convert.py
+++ b/sktime/datatypes/_panel/_convert.py
@@ -35,10 +35,23 @@ __all__ = [
 
 from sktime.datatypes._convert_utils._coerce import _coerce_df_dtypes
 from sktime.datatypes._convert_utils._convert import _extend_conversions
-from sktime.datatypes._panel._registry import MTYPE_LIST_PANEL
 from sktime.utils.dependencies import _check_soft_dependencies
 from sktime.utils.pandas import df_map
 
+# this needs to be refactored with the convert module
+MTYPE_LIST_PANEL = [
+    "nested_univ",
+    "numpy3D",
+    "numpyflat",
+    "pd-multiindex",
+    "pd-wide",
+    "pd-long",
+    "df-list",
+    "gluonts_ListDataset_panel",
+    "gluonts_PandasDataset_panel",
+    "polars_panel",
+]
+
 # dictionary indexed by triples of types
 #  1st element = convert from - type
 #  2nd element = convert to - type
diff --git a/sktime/datatypes/_panel/_registry.py b/sktime/datatypes/_panel/_registry.py
deleted file mode 100644
index 344326eef..000000000
--- a/sktime/datatypes/_panel/_registry.py
+++ /dev/null
@@ -1,63 +0,0 @@
-"""Registry of mtypes for Panel scitype.
-
-See datatypes._registry for API.
-"""
-
-__all__ = [
-    "MTYPE_REGISTER_PANEL",
-    "MTYPE_LIST_PANEL",
-    "MTYPE_SOFT_DEPS_PANEL",
-]
-
-
-MTYPE_REGISTER_PANEL = [
-    (
-        "nested_univ",
-        "Panel",
-        "pd.DataFrame with one column per variable, pd.Series in cells",
-    ),
-    (
-        "numpy3D",
-        "Panel",
-        "3D np.array of format (n_instances, n_columns, n_timepoints)",
-    ),
-    (
-        "numpyflat",
-        "Panel",
-        "WARNING: only for internal use, not a fully supported Panel mtype. "
-        "2D np.array of format (n_instances, n_columns*n_timepoints)",
-    ),
-    ("pd-multiindex", "Panel", "pd.DataFrame with multi-index (instances, timepoints)"),
-    ("pd-wide", "Panel", "pd.DataFrame in wide format, cols = (instance*timepoints)"),
-    (
-        "pd-long",
-        "Panel",
-        "pd.DataFrame in long format, cols = (index, time_index, column)",
-    ),
-    ("df-list", "Panel", "list of pd.DataFrame"),
-    (
-        "gluonts_ListDataset_panel",
-        "Panel",
-        "gluonTS representation of univariate and multivariate time series",
-    ),
-    (
-        "gluonts_PandasDataset_panel",
-        "Panel",
-        "gluonTS representation of a pandas DataFrame",
-    ),
-    (
-        "polars_panel",
-        "Panel",
-        "Polars frame representing a Panel, with one instance and one time index",
-    ),
-]
-
-MTYPE_SOFT_DEPS_PANEL = {
-    "xr.DataArray": "xarray",
-    "dask_panel": "dask",
-    "gluonts_ListDataset_panel": "gluonts",
-    "gluonts_PandasDataset_panel": "gluonts",
-    "polars_panel": "polars",
-}
-
-MTYPE_LIST_PANEL = [x[0] for x in MTYPE_REGISTER_PANEL]
diff --git a/sktime/datatypes/_proba/__init__.py b/sktime/datatypes/_proba/__init__.py
index 5f166c037..4098a2dec 100644
--- a/sktime/datatypes/_proba/__init__.py
+++ b/sktime/datatypes/_proba/__init__.py
@@ -1,10 +1,5 @@
 """Type checkers, converters and mtype inference for probabilistic return types."""
 
 from sktime.datatypes._proba._convert import convert_dict as convert_dict_Proba
-from sktime.datatypes._proba._registry import MTYPE_LIST_PROBA, MTYPE_REGISTER_PROBA
 
-__all__ = [
-    "convert_dict_Proba",
-    "MTYPE_LIST_PROBA",
-    "MTYPE_REGISTER_PROBA",
-]
+__all__ = ["convert_dict_Proba"]
diff --git a/sktime/datatypes/_proba/_check.py b/sktime/datatypes/_proba/_check.py
index bc7f18d33..de06fe70f 100644
--- a/sktime/datatypes/_proba/_check.py
+++ b/sktime/datatypes/_proba/_check.py
@@ -68,6 +68,7 @@ class ProbaPredQuantiles(ScitypeProba):
         "name": "pred_quantiles",  # any string
         "name_python": "proba_pred_quantiles",  # lower_snake_case
         "name_aliases": [],
+        "description": "pandas.DataFrame based specification of predictive quantiles",
         "python_version": None,
         "python_dependencies": "pandas",
     }
@@ -176,6 +177,7 @@ class ProbaPredInterval(ScitypeProba):
         "name": "pred_interval",  # any string
         "name_python": "proba_pred_interval",  # lower_snake_case
         "name_aliases": [],
+        "description": "pandas.DataFrame based specification of predictive intervals",
         "python_version": None,
         "python_dependencies": "pandas",
     }
diff --git a/sktime/datatypes/_proba/_convert.py b/sktime/datatypes/_proba/_convert.py
index e8345d7c7..3b95130b3 100644
--- a/sktime/datatypes/_proba/_convert.py
+++ b/sktime/datatypes/_proba/_convert.py
@@ -33,7 +33,8 @@ __all__ = ["convert_dict"]
 import numpy as np
 import pandas as pd
 
-from sktime.datatypes._proba._registry import MTYPE_LIST_PROBA
+# this needs to be refactored with the convert module
+MTYPE_LIST_PROBA = ["pred_interval", "pred_quantiles"]
 
 ##############################################################
 # methods to convert one machine type to another machine type
diff --git a/sktime/datatypes/_proba/_registry.py b/sktime/datatypes/_proba/_registry.py
deleted file mode 100644
index 98f4245e0..000000000
--- a/sktime/datatypes/_proba/_registry.py
+++ /dev/null
@@ -1,19 +0,0 @@
-"""Registry of mtypes for Proba scitype.
-
-See datatypes._registry for API.
-"""
-
-__all__ = [
-    "MTYPE_REGISTER_PROBA",
-    "MTYPE_LIST_PROBA",
-]
-
-
-MTYPE_REGISTER_PROBA = [
-    ("pred_interval", "Proba", "predictive intervals"),
-    ("pred_quantiles", "Proba", "quantile predictions"),
-    ("pred_var", "Proba", "variance predictions"),
-    # ("pred_dost", "Proba", "full distribution predictions, tensorflow-probability"),
-]
-
-MTYPE_LIST_PROBA = [x[0] for x in MTYPE_REGISTER_PROBA]
diff --git a/sktime/datatypes/_registry.py b/sktime/datatypes/_registry.py
index 461a07551..651b1e419 100644
--- a/sktime/datatypes/_registry.py
+++ b/sktime/datatypes/_registry.py
@@ -38,60 +38,199 @@ mtype_to_scitype(mtype: str) - convenience function that returns scitype for an
 ---
 """
 
-from sktime.datatypes._alignment._registry import (
-    MTYPE_LIST_ALIGNMENT,
-    MTYPE_REGISTER_ALIGNMENT,
-)
-from sktime.datatypes._hierarchical._registry import (
-    MTYPE_LIST_HIERARCHICAL,
-    MTYPE_REGISTER_HIERARCHICAL,
-    MTYPE_SOFT_DEPS_HIERARCHICAL,
-)
-from sktime.datatypes._panel._registry import (
-    MTYPE_LIST_PANEL,
-    MTYPE_REGISTER_PANEL,
-    MTYPE_SOFT_DEPS_PANEL,
-)
-from sktime.datatypes._proba._registry import MTYPE_LIST_PROBA, MTYPE_REGISTER_PROBA
-from sktime.datatypes._series._registry import (
-    MTYPE_LIST_SERIES,
-    MTYPE_REGISTER_SERIES,
-    MTYPE_SOFT_DEPS_SERIES,
-)
-from sktime.datatypes._table._registry import MTYPE_LIST_TABLE, MTYPE_REGISTER_TABLE
-
-MTYPE_REGISTER = []
-MTYPE_REGISTER += MTYPE_REGISTER_SERIES
-MTYPE_REGISTER += MTYPE_REGISTER_PANEL
-MTYPE_REGISTER += MTYPE_REGISTER_HIERARCHICAL
-MTYPE_REGISTER += MTYPE_REGISTER_ALIGNMENT
-MTYPE_REGISTER += MTYPE_REGISTER_TABLE
-MTYPE_REGISTER += MTYPE_REGISTER_PROBA
+from functools import lru_cache
+
+
+def _only_core_deps(cls):
+    """Return True if the class has only core dependencies."""
+    # dependencies implied by the core requirements
+    # that may appear in the classes as python_dependencies tag
+    # it is assumed that only simple dependency strings, no version requirements appear
+    DEPS_PRESENT_IN_ENV = ["numpy", "pandas"]
+
+    deps_tag = cls.get_tag("python_dependencies")
+
+    if deps_tag is None:
+        return True
+    if not isinstance(deps_tag, (list, tuple)) and deps_tag in DEPS_PRESENT_IN_ENV:
+        return True
+    if isinstance(deps_tag, (list, tuple)):
+        return all([x in DEPS_PRESENT_IN_ENV for x in deps_tag])
+    return False
+
+
+def generate_mtype_cls_list(soft_deps="present"):
+    """Generate list of mtype classes using lookup.
+
+    Parameters
+    ----------
+    softdeps : str, optional, default = "present"
+        how inclusion in relation to presence of soft dependencies is handled
+
+        * "exclude" = only classes that do not require soft dependencies are returned
+        * "present" = only classes with soft deps satisfied by the current python
+        environment are returned
+        * "all" = all classes, irrespective of soft deps satisfied or required, returned
+        any other value defaults to "all"
+
+    Returns
+    -------
+    classes : list of classes
+        all classes that are mtypes, i.e. subclasses of BaseDatatype
+        and not starting with "Base" or "Scitype"
+    """
+    if soft_deps not in ["exclude", "present", "all"]:
+        raise ValueError(
+            "Error in soft_deps argument in generate_scitype_cls_list: "
+            "soft_deps must be one of 'exclude', 'present', 'all', "
+            f"but got {soft_deps}"
+        )
+    return _generate_mtype_cls_list(soft_deps=soft_deps).copy()
+
+
+@lru_cache(maxsize=3)
+def _generate_mtype_cls_list(soft_deps="present"):
+    """Generate list of scitype classes using lookup, cached function."""
+    from skbase.utils.dependencies import _check_estimator_deps
+
+    from sktime.datatypes._base import BaseDatatype
+    from sktime.utils.retrieval import _all_classes
+
+    classes = _all_classes("sktime.datatypes")
+    classes = [x[1] for x in classes]
+    classes = [x for x in classes if issubclass(x, BaseDatatype)]
+    classes = [x for x in classes if not x.__name__.startswith("Base")]
+    classes = [x for x in classes if not x.__name__.startswith("Scitype")]
+
+    # subset only to data types with soft dependencies present
+    if soft_deps == "present":
+        classes = [x for x in classes if _check_estimator_deps(x, severity="none")]
+    elif soft_deps == "exclude":
+        classes = [x for x in classes if _only_core_deps(x)]
+    # elif soft_deps=="all", no filtering happens
+
+    return classes
+
+
+def generate_mtype_register(scitype=None, soft_deps="all"):
+    """Generate mtype class register using lookup.
+
+    Parameters
+    ----------
+    scitype str or None, optional, default = None
+        optional scitype to restrict the mtypes to
+
+        * if None, all mtypes are returned
+        * if str, must be scitype string, only mtypes for the scitype are returned
+
+    softdeps : str, optional, default = "all"
+        how inclusion in relation to presence of soft dependencies is handled
+
+        * "exclude" = only classes that do not require soft dependencies are returned
+        * "present" = only classes with soft deps satisfied by the current python
+        environment are returned
+        * "all" = all classes, irrespective of soft deps satisfied or required, returned
+        any other value defaults to "all"
+
+    Returns
+    -------
+    register : list of tuples
+        each tuple corresponds to an mtype, elements as follows:
+
+        0 : string - name of the mtype as used throughout sktime and in datatypes
+
+        1 : string - name of the scitype the mtype is for, must be in SCITYPE_REGISTER
+
+        2 : string - plain English description of the scitype
+    """
+    return _generate_mtype_register_subset(scitype=scitype, soft_deps=soft_deps)
+
+
+@lru_cache(maxsize=256)
+def _generate_mtype_register_subset(scitype=None, soft_deps="all"):
+    """Generate mtype class register using lookup, cached function."""
+    full_register = _generate_mtype_register(soft_deps=soft_deps)
+    if scitype is None:
+        return full_register.copy()
+    else:
+        return [x for x in full_register if x[1] == scitype]
+
+
+@lru_cache(maxsize=3)
+def _generate_mtype_register(soft_deps="all"):
+    """Generate mtype class register using lookup, cached function."""
+    classes = _generate_mtype_cls_list(soft_deps=soft_deps)
+
+    def to_tuple(cls):
+        """Return tuple of mtype register elements."""
+        mtype = cls.get_class_tag("name")
+        scitype = cls.get_class_tag("scitype")
+        desc = cls.get_class_tag("description")
+        return mtype, scitype, desc
+
+    register = [to_tuple(x) for x in classes]
+    return register
+
+
+def generate_mtype_list(scitype=None, soft_deps="all"):
+    """Generate mtype list using lookup.
+
+    Parameters
+    ----------
+    scitype str or None, optional, default = None
+        optional scitype to restrict the mtypes to
+
+        * if None, all mtypes are returned
+        * if str, must be scitype string, only mtypes for the scitype are returned
+
+    softdeps : str, optional, default = "all"
+        how inclusion in relation to presence of soft dependencies is handled
+
+        * "exclude" = only classes that do not require soft dependencies are returned
+        * "present" = only classes with soft deps satisfied by the current python
+        environment are returned
+        * "all" = all classes, irrespective of soft deps satisfied or required, returned
+        any other value defaults to "all"
+
+    Returns
+    -------
+    register : list of string
+        entries are name of the mtype as used throughout sktime and in datatypes
+    """
+    return [x[0] for x in generate_mtype_register(scitype=scitype, soft_deps=soft_deps)]
+
+
+MTYPE_SOFT_DEPS_SERIES = {
+    "xr.DataArray": "xarray",
+    "dask_series": "dask",
+    "pl.DataFrame": "polars",
+    "gluonts_ListDataset_series": "gluonts",
+    "gluonts_PandasDataset_series": "gluonts",
+}
+
+MTYPE_SOFT_DEPS_PANEL = {
+    "xr.DataArray": "xarray",
+    "dask_panel": "dask",
+    "gluonts_ListDataset_panel": "gluonts",
+    "gluonts_PandasDataset_panel": "gluonts",
+    "polars_panel": "polars",
+}
+
+MTYPE_SOFT_DEPS_HIERARCHICAL = {
+    "dask_hierarchical": "dask",
+    "polars_hierarchical": "polars",
+}
 
 MTYPE_SOFT_DEPS = {}
 MTYPE_SOFT_DEPS.update(MTYPE_SOFT_DEPS_SERIES)
 MTYPE_SOFT_DEPS.update(MTYPE_SOFT_DEPS_PANEL)
 MTYPE_SOFT_DEPS.update(MTYPE_SOFT_DEPS_HIERARCHICAL)
 
-
 # mtypes to exclude in checking since they are ambiguous and rare
-AMBIGUOUS_MTYPES = ["numpyflat", "alignment_loc"]
-
-# all time series mtypes excluding ambiguous ones
-ALL_TIME_SERIES_MTYPES = (
-    list(MTYPE_LIST_PANEL) + list(MTYPE_LIST_SERIES) + list(MTYPE_LIST_HIERARCHICAL)
-)
-ALL_TIME_SERIES_MTYPES = list(set(ALL_TIME_SERIES_MTYPES).difference(AMBIGUOUS_MTYPES))
+AMBIGUOUS_MTYPES = ["numpyflat", "alignment_loc", "pd-long", "pd-wide"]
 
 
 __all__ = [
-    "MTYPE_REGISTER",
-    "MTYPE_LIST_HIERARCHICAL",
-    "MTYPE_LIST_PANEL",
-    "MTYPE_LIST_SERIES",
-    "MTYPE_LIST_ALIGNMENT",
-    "MTYPE_LIST_TABLE",
-    "MTYPE_LIST_PROBA",
     "MTYPE_SOFT_DEPS",
     "SCITYPE_REGISTER",
 ]
@@ -153,7 +292,7 @@ def mtype_to_scitype(mtype: str, return_unique=False, coerce_to_list=False):
             "mtype must be str, or list of str, nested list/str object, or None"
         )
 
-    scitype = [k[1] for k in MTYPE_REGISTER if k[0] == mtype]
+    scitype = [k[1] for k in generate_mtype_register() if k[0] == mtype]
 
     if len(scitype) > 1:
         raise ValueError("multiple scitypes match the mtype, specify scitype")
@@ -215,7 +354,7 @@ def scitype_to_mtype(scitype: str, softdeps: str = "exclude"):
             f'"{scitype}" is not a valid scitype string, see datatypes.SCITYPE_REGISTER'
         )
 
-    mtypes = [k[0] for k in MTYPE_REGISTER if k[1] == scitype]
+    mtypes = [k[0] for k in generate_mtype_register() if k[1] == scitype]
 
     if len(mtypes) == 0:
         # if there are no mtypes, this must have been reached by mistake/bug
diff --git a/sktime/datatypes/_series/__init__.py b/sktime/datatypes/_series/__init__.py
index 5f6e59d94..b45d1816c 100644
--- a/sktime/datatypes/_series/__init__.py
+++ b/sktime/datatypes/_series/__init__.py
@@ -1,10 +1,5 @@
 """Module exports: Series type checkers, converters and mtype inference."""
 
 from sktime.datatypes._series._convert import convert_dict as convert_dict_Series
-from sktime.datatypes._series._registry import MTYPE_LIST_SERIES, MTYPE_REGISTER_SERIES
 
-__all__ = [
-    "convert_dict_Series",
-    "MTYPE_LIST_SERIES",
-    "MTYPE_REGISTER_SERIES",
-]
+__all__ = ["convert_dict_Series"]
diff --git a/sktime/datatypes/_series/_check.py b/sktime/datatypes/_series/_check.py
index 4e3904cf6..1de2d801a 100644
--- a/sktime/datatypes/_series/_check.py
+++ b/sktime/datatypes/_series/_check.py
@@ -112,6 +112,7 @@ class SeriesPdDataFrame(ScitypeSeries):
         "name": "pd.DataFrame",  # any string
         "name_python": "series_pd_df",  # lower_snake_case
         "name_aliases": [],
+        "description": "pandas.DataFrame representation of a uni- or multivariate series",  # noqa: E501
         "python_version": None,
         "python_dependencies": "pandas",
         "python_type": "pandas.DataFrame",
@@ -272,6 +273,7 @@ class SeriesPdSeries(ScitypeSeries):
         "name": "pd.Series",  # any string
         "name_python": "series_pd_sr",  # lower_snake_case
         "name_aliases": [],
+        "description": "pandas.Series representation of a univariate series",
         "python_version": None,
         "python_dependencies": "pandas",
         "python_type": "pandas.Series",
@@ -417,6 +419,7 @@ class SeriesNp2D(ScitypeSeries):
         "name": "np.ndarray",  # any string
         "name_python": "series_pd_np",  # lower_snake_case
         "name_aliases": [],
+        "description": "2D numpy.ndarray with rows=samples, cols=variables, index=integers",  # noqa: E501
         "python_version": None,
         "python_dependencies": "numpy",
         "python_type": "numpy.ndarray",
@@ -632,6 +635,7 @@ class SeriesXarray(ScitypeSeries):
         "name": "xr.DataArray",  # any string
         "name_python": "series_xarray",  # lower_snake_case
         "name_aliases": [],
+        "description": "xarray.DataArray representation of a uni- or multivariate time series",  # noqa: E501
         "python_version": None,
         "python_dependencies": "xarray",
         "python_type": "xarray.DataArray",
@@ -765,6 +769,7 @@ class SeriesDask(ScitypeSeries):
         "name": "dask_series",  # any string
         "name_python": "series_dask",  # lower_snake_case
         "name_aliases": [],
+        "description": "dask.DataFrame representation of a uni- or multivariate series",
         "python_version": None,
         "python_dependencies": "dask",
         "python_type": "dask.dataframe",
@@ -835,6 +840,7 @@ class SeriesPolarsEager(ScitypeSeries):
         "name": "pl.DataFrame",  # any string
         "name_python": "series_polars_eager",  # lower_snake_case
         "name_aliases": [],
+        "description": "polars.DataFrame representation of a uni- or multivariate series",  # noqa: E501
         "python_version": None,
         "python_dependencies": "polars",
         "python_type": "polars.DataFrame",
@@ -911,6 +917,7 @@ class SeriesGluontsList(ScitypeSeries):
         "name": "gluonts_ListDataset_series",  # any string
         "name_python": "series_gluonts_listdataset",  # lower_snake_case
         "name_aliases": [],
+        "description": "gluonts ListDataset representation of a uni- or multivariate series",  # noqa: E501
         "python_version": None,
         "python_dependencies": "gluonts",
         "python_type": "list",
@@ -1055,6 +1062,7 @@ class SeriesGluontsPandas(ScitypeSeries):
         "name": "gluonts_PandasDataset_series",  # any string
         "name_python": "series_gluonts_pandasdataset",  # lower_snake_case
         "name_aliases": [],
+        "description": "gluonts PandasDataset representation of a uni- or multivariate series",  # noqa: E501
         "python_version": None,
         "python_dependencies": "gluonts",
         "python_type": "gluonts.PandasDataset",
@@ -1132,7 +1140,7 @@ class SeriesGluontsPandas(ScitypeSeries):
         if _req("has_nans", return_metadata):
             metadata["has_nans"] = df.isna().any().any()
 
-        if _req("dtypekind_dfip", return_metadata):
+        if _req(["feature_kind", "dtypekind_dfip"], return_metadata):
             index_cols_count = len(df.columns)
 
             # slicing off additional index columns
diff --git a/sktime/datatypes/_series/_convert.py b/sktime/datatypes/_series/_convert.py
index ee1e50efc..2794e95c7 100644
--- a/sktime/datatypes/_series/_convert.py
+++ b/sktime/datatypes/_series/_convert.py
@@ -38,9 +38,20 @@ import pandas as pd
 ##############################################################
 from sktime.datatypes._convert_utils._coerce import _coerce_df_dtypes
 from sktime.datatypes._convert_utils._convert import _extend_conversions
-from sktime.datatypes._series._registry import MTYPE_LIST_SERIES
 from sktime.utils.dependencies import _check_soft_dependencies
 
+# this needs to be refactored with the convert module
+MTYPE_LIST_SERIES = [
+    "pd.Series",
+    "pd.DataFrame",
+    "np.ndarray",
+    "xr.DataArray",
+    "dask_series",
+    "pl.DataFrame",
+    "gluonts_ListDataset_series",
+    "gluonts_PandasDataset_series",
+]
+
 convert_dict = dict()
 
 
diff --git a/sktime/datatypes/_series/_registry.py b/sktime/datatypes/_series/_registry.py
deleted file mode 100644
index a0d888410..000000000
--- a/sktime/datatypes/_series/_registry.py
+++ /dev/null
@@ -1,54 +0,0 @@
-"""Registry of mtypes for Series scitype.
-
-See datatypes._registry for API.
-"""
-
-__all__ = [
-    "MTYPE_REGISTER_SERIES",
-    "MTYPE_LIST_SERIES",
-    "MTYPE_SOFT_DEPS_SERIES",
-]
-
-
-MTYPE_REGISTER_SERIES = [
-    ("pd.Series", "Series", "pd.Series representation of a univariate series"),
-    (
-        "pd.DataFrame",
-        "Series",
-        "pd.DataFrame representation of a uni- or multivariate series",
-    ),
-    (
-        "np.ndarray",
-        "Series",
-        "2D numpy.ndarray with rows=samples, cols=variables, index=integers",
-    ),
-    (
-        "xr.DataArray",
-        "Series",
-        "xr.DataArray representation of a uni- or multivariate series",
-    ),
-    (
-        "dask_series",
-        "Series",
-        "xdas representation of a uni- or multivariate series",
-    ),
-    (
-        "pl.DataFrame",
-        "Series",
-        "pl.DataFrame representation of a uni- or multivariate series",
-    ),
-    (
-        "gluonts_ListDataset_series",
-        "Series",
-        "gluonTS representation of univariate and multivariate series",
-    ),
-]
-
-MTYPE_SOFT_DEPS_SERIES = {
-    "xr.DataArray": "xarray",
-    "dask_series": "dask",
-    "pl.DataFrame": "polars",
-    "gluonts_ListDataset_series": "gluonts",
-}
-
-MTYPE_LIST_SERIES = [x[0] for x in MTYPE_REGISTER_SERIES]
diff --git a/sktime/datatypes/_table/__init__.py b/sktime/datatypes/_table/__init__.py
index dbdfd021c..d06e68a57 100644
--- a/sktime/datatypes/_table/__init__.py
+++ b/sktime/datatypes/_table/__init__.py
@@ -1,10 +1,5 @@
 """Module exports: Series type checkers, converters and mtype inference."""
 
 from sktime.datatypes._table._convert import convert_dict as convert_dict_Table
-from sktime.datatypes._table._registry import MTYPE_LIST_TABLE, MTYPE_REGISTER_TABLE
 
-__all__ = [
-    "convert_dict_Table",
-    "MTYPE_LIST_TABLE",
-    "MTYPE_REGISTER_TABLE",
-]
+__all__ = ["convert_dict_Table"]
diff --git a/sktime/datatypes/_table/_check.py b/sktime/datatypes/_table/_check.py
index a9c959cae..6464c6c72 100644
--- a/sktime/datatypes/_table/_check.py
+++ b/sktime/datatypes/_table/_check.py
@@ -102,6 +102,7 @@ class TablePdDataFrame(ScitypeTable):
         "name": "pd_DataFrame_Table",  # any string
         "name_python": "table_pd_df",  # lower_snake_case
         "name_aliases": [],
+        "description": "pandas.DataFrame representation of a data table",
         "python_version": None,
         "python_dependencies": "pandas",
         "python_type": "pandas.DataFrame",
@@ -223,6 +224,7 @@ class TablePdSeries(ScitypeTable):
         "name": "pd_Series_Table",  # any string
         "name_python": "table_pd_series",  # lower_snake_case
         "name_aliases": [],
+        "description": "pandas.Series representation of a data table",
         "python_version": None,
         "python_dependencies": "pandas",
         "python_type": "pandas.Series",
@@ -350,6 +352,7 @@ class TableNp1D(ScitypeTable):
         "name": "numpy1D",  # any string
         "name_python": "table_numpy1d",  # lower_snake_case
         "name_aliases": [],
+        "description": "1D np.narray representation of a univariate data table",
         "python_version": None,
         "python_dependencies": "numpy",
         "python_type": "numpy.ndarray",
@@ -475,6 +478,7 @@ class TableNp2D(ScitypeTable):
         "name": "numpy2D",  # any string
         "name_python": "table_numpy2d",  # lower_snake_case
         "name_aliases": [],
+        "description": "2D np.narray representation of a multivariate data table",
         "python_version": None,
         "python_dependencies": "numpy",
         "python_type": "numpy.ndarray",
@@ -599,6 +603,7 @@ class TableListOfDict(ScitypeTable):
         "name": "list_of_dict",  # any string
         "name_python": "table_list_of_dict",  # lower_snake_case
         "name_aliases": [],
+        "description": "list of dictionaries with primitive entries",
         "python_version": None,
         "python_dependencies": "numpy",
         "python_type": "list",
@@ -744,6 +749,7 @@ class TablePolarsEager(ScitypeTable):
         "name": "polars_eager_table",  # any string
         "name_python": "table_polars_eager",  # lower_snake_case
         "name_aliases": [],
+        "description": "eager polars.DataFrame representation of a data table",
         "python_version": None,
         "python_dependencies": ["polars", "pyarrow"],
         "python_type": "polars.DataFrame",
@@ -810,6 +816,7 @@ class TablePolarsLazy(ScitypeTable):
         "name": "polars_lazy_table",  # any string
         "name_python": "table_polars_lazy",  # lower_snake_case
         "name_aliases": [],
+        "description": "lazy polars.DataFrame representation of a data table",
         "python_version": None,
         "python_dependencies": ["polars", "pyarrow"],
         "python_type": "polars.LazyFrame",
diff --git a/sktime/datatypes/_table/_convert.py b/sktime/datatypes/_table/_convert.py
index 8e078d4a7..abf6c633c 100644
--- a/sktime/datatypes/_table/_convert.py
+++ b/sktime/datatypes/_table/_convert.py
@@ -34,9 +34,19 @@ import numpy as np
 import pandas as pd
 
 from sktime.datatypes._convert_utils._convert import _extend_conversions
-from sktime.datatypes._table._registry import MTYPE_LIST_TABLE
 from sktime.utils.dependencies import _check_soft_dependencies
 
+# this needs to be refactored with the convert module
+MTYPE_LIST_TABLE = [
+    "pd_DataFrame_Table",
+    "numpy1D",
+    "numpy2D",
+    "pd_Series_Table",
+    "list_of_dict",
+    "polars_eager_table",
+    "polars_lazy_table",
+]
+
 ##############################################################
 # methods to convert one machine type to another machine type
 ##############################################################
diff --git a/sktime/datatypes/_table/_registry.py b/sktime/datatypes/_table/_registry.py
deleted file mode 100644
index f7f7974cf..000000000
--- a/sktime/datatypes/_table/_registry.py
+++ /dev/null
@@ -1,22 +0,0 @@
-"""Registry of mtypes for Table scitype.
-
-See datatypes._registry for API.
-"""
-
-__all__ = [
-    "MTYPE_REGISTER_TABLE",
-    "MTYPE_LIST_TABLE",
-]
-
-
-MTYPE_REGISTER_TABLE = [
-    ("pd_DataFrame_Table", "Table", "pd.DataFrame representation of a data table"),
-    ("numpy1D", "Table", "1D np.narray representation of a univariate data table"),
-    ("numpy2D", "Table", "2D np.narray representation of a multivariate data table"),
-    ("pd_Series_Table", "Table", "pd.Series representation of a univariate data table"),
-    ("list_of_dict", "Table", "list of dictionaries with primitive entries"),
-    ("polars_eager_table", "Table", "polars.DataFrame representation of a data table"),
-    ("polars_lazy_table", "Table", "polars.LazyFrame representation of a data table"),
-]
-
-MTYPE_LIST_TABLE = [x[0] for x in MTYPE_REGISTER_TABLE]
diff --git a/sktime/detection/base/__init__.py b/sktime/detection/base/__init__.py
index f38ab92b3..29a3e2a6a 100644
--- a/sktime/detection/base/__init__.py
+++ b/sktime/detection/base/__init__.py
@@ -2,6 +2,6 @@
 # copyright: sktime developers, BSD-3-Clause License (see LICENSE file)
 """Implements base classes for detection tasks in sktime."""
 
-__all__ = ["BaseDetector", "BaseSeriesAnnotator"]
+__all__ = ["BaseDetector"]
 
-from sktime.detection.base._base import BaseDetector, BaseSeriesAnnotator
+from sktime.detection.base._base import BaseDetector
diff --git a/sktime/detection/base/_base.py b/sktime/detection/base/_base.py
index 2a1e10949..3e4c6762b 100644
--- a/sktime/detection/base/_base.py
+++ b/sktime/detection/base/_base.py
@@ -19,9 +19,8 @@ State:
     fitted state flag       - check_is_fitted()
 """
 
-# todo 0.37.0: remove BaseSeriesAnnotator
 __author__ = ["fkiraly", "tveten", "alex-jg3", "satya-pattnaik"]
-__all__ = ["BaseDetector", "BaseSeriesAnnotator"]
+__all__ = ["BaseDetector"]
 
 import numpy as np
 import pandas as pd
@@ -30,7 +29,6 @@ from sktime.base import BaseEstimator
 from sktime.datatypes import check_is_error_msg, check_is_scitype, convert
 from sktime.utils.adapters._safe_call import _method_has_arg
 from sktime.utils.validation.series import check_series
-from sktime.utils.warnings import warn
 
 
 class BaseDetector(BaseEstimator):
@@ -74,9 +72,8 @@ class BaseDetector(BaseEstimator):
         "python_dependencies": None,  # str or list of str, package soft dependencies
         # estimator tags
         # --------------
-        # todo 0.37.0 switch order of series-annotator and detector
         # todo 1.0.0 - remove series-annotator
-        "object_type": ["series-annotator", "detector"],  # type of object
+        "object_type": ["detector", "series-annotator"],  # type of object
         "learning_type": "None",  # supervised, unsupervised
         "task": "None",  # anomaly_detection, change_point_detection, segmentation
         "capability:multivariate": False,
@@ -134,8 +131,7 @@ class BaseDetector(BaseEstimator):
         else:
             return NotImplemented
 
-    # todo 0.37.0: remove the Y parameter and related handling
-    def fit(self, X, y=None, Y=None):
+    def fit(self, X, y=None):
         """Fit to training data.
 
         Parameters
@@ -185,19 +181,6 @@ class BaseDetector(BaseEstimator):
             self._is_fitted = True
             return self
 
-        if Y is not None:
-            warn(
-                "Warning: the Y parameter in detection/annotation algorithms "
-                "is deprecated and will be removed in the 0.37.0 release. "
-                "Users should use the y parameter instead. "
-                "Until the 0.37.0 release, the Y parameter will be used if "
-                "no y parameter is provided, ensuring backwards compatibility.",
-                stacklevel=2,
-            )
-
-        if Y is not None and y is None:
-            y = Y
-
         self._X = X
         self._y = y
 
@@ -205,18 +188,6 @@ class BaseDetector(BaseEstimator):
 
         if _method_has_arg(self._fit, "y"):
             self._fit(X=X, y=y)
-        elif _method_has_arg(self._fit, "Y"):
-            self._fit(X=X, Y=y)
-            warn(
-                "Warning: the Y parameter in detection/annotation algorithms "
-                "is deprecated and will be removed in the 0.37.0 release. "
-                "Users should use the y parameter instead. "
-                f"The class {self.__class__.__name__} uses the Y parameter "
-                "internally in _fit, this should be replaced with y by a maintainer. "
-                f"Until the 0.37.0 release, this will raise no exceptions, "
-                "ensuring backwards compatibility.",
-                stacklevel=2,
-            )
         else:
             self._fit(X=X_inner)
 
@@ -349,7 +320,7 @@ class BaseDetector(BaseEstimator):
 
         return pd.DataFrame(scores)
 
-    def update(self, X, y=None, Y=None):
+    def update(self, X, y=None):
         """Update model with new data and optional ground truth labels.
 
         Parameters
@@ -376,19 +347,6 @@ class BaseDetector(BaseEstimator):
         if self.get_tag("fit_is_empty", False):
             return self
 
-        if Y is not None:
-            warn(
-                "Warning: the Y parameter in detection/annotation algorithms "
-                "is deprecated and will be removed in the 0.37.0 release. "
-                "Users should use the y parameter instead. "
-                "Until the 0.37.0 release, the Y parameter will be used if "
-                "no y parameter is provided, ensuring backwards compatibility.",
-                stacklevel=2,
-            )
-
-        if y is None and Y is not None:
-            y = Y
-
         self._X = X_inner.combine_first(self._X)
 
         if y is not None:
@@ -396,8 +354,6 @@ class BaseDetector(BaseEstimator):
 
         if _method_has_arg(self._update, "y"):
             self._update(X=X_inner, y=y)
-        elif _method_has_arg(self._update, "Y"):
-            self._update(X=X_inner, Y=y)
         else:
             self._update(X=X_inner)
 
@@ -465,8 +421,7 @@ class BaseDetector(BaseEstimator):
 
         return y
 
-    # todo 0.37.0: remove Y argument
-    def fit_predict(self, X, y=None, Y=None):
+    def fit_predict(self, X, y=None):
         """Fit to data, then predict it.
 
         Fits model to X and Y with given detection parameters
@@ -527,10 +482,9 @@ class BaseDetector(BaseEstimator):
         """
         # Non-optimized default implementation; override when a better
         # method is possible for a given algorithm.
-        return self.fit(X, y=y, Y=Y).predict(X)
+        return self.fit(X, y=y).predict(X)
 
-    # todo 0.37.0: remove Y argument
-    def fit_transform(self, X, y=None, Y=None):
+    def fit_transform(self, X, y=None):
         """Fit to data, then transform it.
 
         Fits model to X and Y with given detection parameters
@@ -561,7 +515,7 @@ class BaseDetector(BaseEstimator):
             * If ``task`` is "segmentation", the values are integer labels of the
               segments. Possible labels are integers starting from 0.
         """
-        y_sparse = self.fit_predict(X, y=y, Y=Y)
+        y_sparse = self.fit_predict(X, y=y)
         y_dense = self.sparse_to_dense(y_sparse, index=X.index)
         y_dense = self._coerce_to_df(y_dense, columns=["labels"])
         return y_dense
@@ -1183,18 +1137,3 @@ class BaseDetector(BaseEstimator):
             return BaseDetector._empty_sparse()
         change_points = y_sparse.set_index("ilocs").index.left
         return change_points
-
-
-class BaseSeriesAnnotator(BaseDetector):
-    """Base class for time series detectors - DEPRECATED - use BaseDetector instead."""
-
-    def __init__(self):
-        super().__init__()
-        warn(
-            "Warning: BaseSeriesAnnotator is deprecated. "
-            "Extension developers should use BaseDetector instead, "
-            "from sktime.detection.base, this is a replacement with "
-            "equivalent functionality. "
-            "The BaseSeriesAnnotator will be removed in the 0.37.0 release.",
-            stacklevel=2,
-        )
diff --git a/sktime/detection/bs.py b/sktime/detection/bs.py
index adcd652c6..959f53301 100644
--- a/sktime/detection/bs.py
+++ b/sktime/detection/bs.py
@@ -39,7 +39,7 @@ class BinarySegmentation(BaseDetector):
     Examples
     --------
     >>> import pandas as pd
-    >>> from sktime.annotation.bs import BinarySegmentation
+    >>> from sktime.detection.bs import BinarySegmentation
     >>> model = BinarySegmentation(threshold=1)
     >>> X = pd.Series([1, 1, 1, 1, 5, 5, 5, 5])
     >>> model.fit_predict(X)
diff --git a/sktime/detection/clasp.py b/sktime/detection/clasp.py
index d7bef3a06..346caf9c9 100644
--- a/sktime/detection/clasp.py
+++ b/sktime/detection/clasp.py
@@ -203,8 +203,8 @@ class ClaSPSegmentation(BaseDetector):
 
     Examples
     --------
-    >>> from sktime.annotation.clasp import ClaSPSegmentation
-    >>> from sktime.annotation.clasp import find_dominant_window_sizes
+    >>> from sktime.detection.clasp import ClaSPSegmentation
+    >>> from sktime.detection.clasp import find_dominant_window_sizes
     >>> from sktime.datasets import load_gun_point_segmentation
     >>> X, true_period_size, cps = load_gun_point_segmentation()
     >>> dominant_period_size = find_dominant_window_sizes(X)
diff --git a/sktime/detection/datagen.py b/sktime/detection/datagen.py
index a3117df20..480ca2735 100644
--- a/sktime/detection/datagen.py
+++ b/sktime/detection/datagen.py
@@ -45,7 +45,7 @@ def piecewise_normal_multivariate(
 
     Examples
     --------
-    >>> from sktime.annotation.datagen import piecewise_normal_multivariate
+    >>> from sktime.detection.datagen import piecewise_normal_multivariate
     >>> piecewise_normal_multivariate(means=[[1, 1], [2, 2], [3, 3]],\
         lengths=[2, 3, 1], random_state=2)
     array([[ 0.58324215,  0.94373317],
@@ -55,7 +55,7 @@ def piecewise_normal_multivariate(
            [ 0.94204778,  1.09099239],
            [ 3.55145404,  5.29220801]])
 
-    >>> from sktime.annotation.datagen import piecewise_normal_multivariate
+    >>> from sktime.detection.datagen import piecewise_normal_multivariate
     >>> piecewise_normal_multivariate(means=[[1, 1], [2, 2], [3, 3]],\
         lengths=[2, 3, 1], variances=[[1.0, 1.0], [1.0, 1.0], [1.0, 1.0]],\
         random_state=2)
@@ -66,7 +66,7 @@ def piecewise_normal_multivariate(
            [ 0.94204778,  1.09099239],
            [ 3.55145404,  5.29220801]])
 
-    >>> from sktime.annotation.datagen import piecewise_normal_multivariate
+    >>> from sktime.detection.datagen import piecewise_normal_multivariate
     >>> piecewise_normal_multivariate(means=[[1, 1], [2, 2], [3, 3]],\
         lengths=[2, 3, 1], covariances=[[[1.0, 0], [0, 1.0]], [[1.0, 0],\
             [0, 1.0]], [[1.0, 0], [0, 1.0]]], random_state=2)
@@ -77,7 +77,7 @@ def piecewise_normal_multivariate(
            [ 0.94204778,  1.09099239],
            [ 3.55145404,  5.29220801]])
 
-    >>> from sktime.annotation.datagen import piecewise_normal_multivariate
+    >>> from sktime.detection.datagen import piecewise_normal_multivariate
     >>> piecewise_normal_multivariate(means=[[1, 3], [4, 5]], lengths=[3, 3],\
         covariances=[[[0.5, 0.3], [0.3, 1.0]], [[1.0, 0.3], [0.3, 0.7]]],\
         random_state=2)
@@ -159,17 +159,17 @@ def piecewise_normal(
 
     Examples
     --------
-    >>> from sktime.annotation.datagen import piecewise_normal
+    >>> from sktime.detection.datagen import piecewise_normal
     >>> piecewise_normal([1, 2, 3], lengths=[2, 4, 8], random_state=42) # doctest: +SKIP
     array([1.49671415, 0.8617357 , 2.64768854, 3.52302986, 1.76584663,
         1.76586304, 4.57921282, 3.76743473, 2.53052561, 3.54256004,
         2.53658231, 2.53427025, 3.24196227, 1.08671976])
 
-    >>> from sktime.annotation.datagen import piecewise_normal
+    >>> from sktime.detection.datagen import piecewise_normal
     >>> piecewise_normal([1, 2, 3], lengths=[2, 4, 8], std_dev=0) # doctest: +SKIP
     array([1., 1., 2., 2., 2., 2., 3., 3., 3., 3., 3., 3., 3., 3.])
 
-    >>> from sktime.annotation.datagen import piecewise_normal
+    >>> from sktime.detection.datagen import piecewise_normal
     >>> piecewise_normal([1, 2, 3], lengths=[2, 4, 8], std_dev=[0, 0.5, 1.0])\
         # doctest: +SKIP
     array([1.        , 1.        , 2.32384427, 2.76151493, 1.88292331,
@@ -224,7 +224,7 @@ def piecewise_multinomial(
 
     Examples
     --------
-    >>> from sktime.annotation.datagen import piecewise_multinomial
+    >>> from sktime.detection.datagen import piecewise_multinomial
     >>> piecewise_multinomial(20, lengths=[3, 2], p_vals=[[1/4, 3/4], \
         [3/4, 1/4]], random_state=42) # doctest: +SKIP
     array([[ 4, 16],
@@ -233,7 +233,7 @@ def piecewise_multinomial(
        [15,  5],
        [17,  3]])
 
-    >>> from sktime.annotation.datagen import piecewise_multinomial
+    >>> from sktime.detection.datagen import piecewise_multinomial
     >>> piecewise_multinomial(10, lengths=[2, 4, 8], \
         p_vals=[[1, 0], [0, 1], [1, 0]]) # doctest: +SKIP
     array([[10,  0],
@@ -294,11 +294,11 @@ def piecewise_poisson(
 
     Examples
     --------
-    >>> from sktime.annotation.datagen import piecewise_poisson
+    >>> from sktime.detection.datagen import piecewise_poisson
     >>> piecewise_poisson(lambdas=[1,2,3],lengths=[2,4,8],random_state=42)#doctest:+SKIP
     array([1, 2, 1, 3, 3, 1, 3, 1, 3, 2, 2, 4, 2, 1])
 
-    >>> from sktime.annotation.datagen import piecewise_poisson
+    >>> from sktime.detection.datagen import piecewise_poisson
     >>> piecewise_poisson(lambdas=[1,3,6],lengths=[2,4,8],random_state=42)#doctest:+SKIP
     array([1, 2, 1, 3, 3, 2, 5, 5, 6, 4, 4, 9, 3, 5])
     """
diff --git a/sktime/detection/eagglo.py b/sktime/detection/eagglo.py
index c111ed7d5..e377fddf3 100644
--- a/sktime/detection/eagglo.py
+++ b/sktime/detection/eagglo.py
@@ -71,10 +71,10 @@ class EAgglo(BaseTransformer):
 
     Examples
     --------
-    >>> from sktime.annotation.datagen import piecewise_normal_multivariate
+    >>> from sktime.detection.datagen import piecewise_normal_multivariate
     >>> X = piecewise_normal_multivariate(means=[[1, 3], [4, 5]], lengths=[3, 4],
     ... random_state = 10)
-    >>> from sktime.annotation.eagglo import EAgglo
+    >>> from sktime.detection.eagglo import EAgglo
     >>> model = EAgglo()
     >>> model.fit_transform(X)
     array([0, 0, 0, 1, 1, 1, 1])
diff --git a/sktime/detection/hmm.py b/sktime/detection/hmm.py
index b098b52d2..41d6d3596 100644
--- a/sktime/detection/hmm.py
+++ b/sktime/detection/hmm.py
@@ -113,7 +113,7 @@ class HMM(BaseDetector):
 
     Examples
     --------
-    >>> from sktime.annotation.hmm import HMM
+    >>> from sktime.detection.hmm import HMM
     >>> from scipy.stats import norm
     >>> from numpy import asarray
     >>> # define the emission probs for our HMM model:
diff --git a/sktime/detection/igts.py b/sktime/detection/igts.py
index 9f0df5add..8dc6f5a34 100644
--- a/sktime/detection/igts.py
+++ b/sktime/detection/igts.py
@@ -154,13 +154,13 @@ class IGTS:
 
     Examples
     --------
-    >>> from sktime.annotation.datagen import piecewise_normal_multivariate
+    >>> from sktime.detection.datagen import piecewise_normal_multivariate
     >>> from sklearn.preprocessing import MinMaxScaler
     >>> X = piecewise_normal_multivariate(lengths=[10, 10, 10, 10],
     ... means=[[0.0, 1.0], [11.0, 10.0], [5.0, 3.0], [2.0, 2.0]],
     ... variances=0.5)
     >>> X_scaled = MinMaxScaler(feature_range=(0, 1)).fit_transform(X)
-    >>> from sktime.annotation.igts import InformationGainSegmentation
+    >>> from sktime.detection.igts import InformationGainSegmentation
     >>> igts = InformationGainSegmentation(k_max=3, step=2)
     >>> y = igts.fit_predict(X_scaled)
     """
@@ -368,7 +368,7 @@ class InformationGainSegmentation(SegmentationMixin, BaseEstimator):
 
     Examples
     --------
-    >>> from sktime.annotation.datagen import piecewise_normal_multivariate
+    >>> from sktime.detection.datagen import piecewise_normal_multivariate
     >>> from sklearn.preprocessing import MinMaxScaler
     >>> X = piecewise_normal_multivariate(
     ... lengths=[10, 10, 10, 10],
@@ -376,7 +376,7 @@ class InformationGainSegmentation(SegmentationMixin, BaseEstimator):
     ... variances=0.5,
     ... )
     >>> X_scaled = MinMaxScaler(feature_range=(0, 1)).fit_transform(X) # doctest: +SKIP
-    >>> from sktime.annotation.igts import InformationGainSegmentation # doctest: +SKIP
+    >>> from sktime.detection.igts import InformationGainSegmentation # doctest: +SKIP
     >>> igts = InformationGainSegmentation(k_max=3, step=2) # doctest: +SKIP
     >>> y = igts.fit_predict(X_scaled) # doctest: +SKIP
     """
diff --git a/sktime/detection/lof.py b/sktime/detection/lof.py
index 0078929bd..9f88955d2 100644
--- a/sktime/detection/lof.py
+++ b/sktime/detection/lof.py
@@ -102,7 +102,7 @@ class SubLOF(BaseDetector):
     Examples
     --------
     >>> import pandas as pd
-    >>> from sktime.annotation.lof import SubLOF
+    >>> from sktime.detection.lof import SubLOF
     >>> model = SubLOF(3, window_size=5, novelty=True)
     >>> x = pd.DataFrame([0, 0.5, 100, 0.1, 0, 0, 0, 100, 0, 0, 0.3, -1, 0, 100, 0.2])
     >>> model.fit_transform(x)
diff --git a/sktime/detection/stray.py b/sktime/detection/stray.py
index 5dcfe6296..c1ee5753e 100644
--- a/sktime/detection/stray.py
+++ b/sktime/detection/stray.py
@@ -62,7 +62,7 @@ class STRAY(BaseTransformer):
 
     Examples
     --------
-    >>> from sktime.annotation.stray import STRAY
+    >>> from sktime.detection.stray import STRAY
     >>> from sktime.datasets import load_airline
     >>> from sklearn.preprocessing import MinMaxScaler
     >>> import numpy as np
diff --git a/sktime/forecasting/base/_fh.py b/sktime/forecasting/base/_fh.py
index 2368b18bd..127c843c4 100644
--- a/sktime/forecasting/base/_fh.py
+++ b/sktime/forecasting/base/_fh.py
@@ -967,7 +967,7 @@ def _index_range(relative, cutoff):
 
 def _is_pandas_arithmetic_bug_fixed():
     """Check if pandas supports correct arithmetic without a workaround."""
-    # TODO: 0.37.0:
+    # TODO: 0.38.0:
     # Check at every minor release whether lower pandas bound >=1.5.0
     # if yes, can remove the workaround in the "else" condition and the check
     #
diff --git a/sktime/forecasting/base/adapters/_pmdarima.py b/sktime/forecasting/base/adapters/_pmdarima.py
index fd336da73..664da8f62 100644
--- a/sktime/forecasting/base/adapters/_pmdarima.py
+++ b/sktime/forecasting/base/adapters/_pmdarima.py
@@ -23,7 +23,7 @@ class _PmdArimaAdapter(BaseForecaster):
         "capability:pred_int:insample": True,
         "requires-fh-in-fit": False,
         "handles-missing-data": True,
-        # TODO 0.37.0: check if numpy 2 incompatiblity can be removed
+        # TODO 0.38.0: check if numpy 2 incompatiblity can be removed
         "python_dependencies": ["pmdarima", "numpy<2"],
     }
 
diff --git a/sktime/forecasting/compose/_hierarchy_ensemble.py b/sktime/forecasting/compose/_hierarchy_ensemble.py
index 53d482273..a0efda3f6 100644
--- a/sktime/forecasting/compose/_hierarchy_ensemble.py
+++ b/sktime/forecasting/compose/_hierarchy_ensemble.py
@@ -210,26 +210,6 @@ class HierarchyEnsembleForecaster(_HeterogenousEnsembleForecaster):
 
         return Aggregator().fit_transform(y)
 
-    @property
-    def fitted_list(self):
-        """Deprecated attribute.
-
-        TODO 0.37.0: Remove this property entirely.
-        """
-        import warnings
-
-        warnings.warn(
-            """The fitted_list property of HierarchyEnsembleForecaster is deprecated
-            and will be removed in sktime 0.37.0.
-            Please use the get_fitted_params method,
-            or the attribute forecasters_ instead.
-            Given a fitted instance f, a read call to f.fitted_list can be replaced
-            by f.get_fitted_params()['forecasters'] or f.forecasters_.
-            """,
-            DeprecationWarning,
-        )
-        return self.fitted_list_
-
     def _fit(self, y, X, fh):
         """Fit to training data.
 
@@ -428,7 +408,7 @@ class HierarchyEnsembleForecaster(_HeterogenousEnsembleForecaster):
                 X = self._aggregate(X)
         x = X
 
-        for forecaster, ind in self.fitted_list:
+        for forecaster, ind in self.fitted_list_:
             if z.index.nlevels == 1:
                 forecaster.update(z, X=x, update_params=update_params)
             else:
@@ -472,7 +452,7 @@ class HierarchyEnsembleForecaster(_HeterogenousEnsembleForecaster):
 
         preds = parallelize(
             _predict_one_forecaster,
-            self.fitted_list,
+            self.fitted_list_,
             meta,
             backend=self.backend,
             backend_params=self.backend_params,
diff --git a/sktime/forecasting/compose/_pipeline.py b/sktime/forecasting/compose/_pipeline.py
index 770bb4045..bef480ea5 100644
--- a/sktime/forecasting/compose/_pipeline.py
+++ b/sktime/forecasting/compose/_pipeline.py
@@ -185,7 +185,7 @@ class _Pipeline(_HeterogenousMetaEstimator, BaseForecaster):
                         if len(levels) == 1:
                             levels = levels[0]
                         yt[ix] = y.xs(ix, level=levels, axis=1)
-                        # todo 0.37.0 - check why this cannot be easily removed
+                        # todo 0.38.0 - check why this cannot be easily removed
                         # in theory, we should get rid of the "Coverage" case treatment
                         # (the legacy naming convention was removed in 0.23.0)
                         # deal with the "Coverage" case, we need to get rid of this
@@ -1830,7 +1830,7 @@ class ForecastX(BaseForecaster):
         params1 = {"forecaster_X": fx, "forecaster_y": fy}
 
         # example with probabilistic capability
-        # todo 0.37.0: check if numpy<2 is still needed
+        # todo 0.38.0: check if numpy<2 is still needed
         if _check_soft_dependencies(["pmdarima", "numpy<2"], severity="none"):
             fy_proba = ARIMA()
         else:
diff --git a/sktime/forecasting/model_selection/__init__.py b/sktime/forecasting/model_selection/__init__.py
index 7b29ec77b..1e947fdf8 100644
--- a/sktime/forecasting/model_selection/__init__.py
+++ b/sktime/forecasting/model_selection/__init__.py
@@ -20,7 +20,7 @@ from sktime.forecasting.model_selection._tune import (
 )
 
 
-# todo 0.37.0 - check whether we should remove, otherwise bump
+# todo 0.38.0 - check whether we should remove, otherwise bump
 # still used in blog posts and old tutorials
 def temporal_train_test_split(
     y, X=None, test_size=None, train_size=None, fh=None, anchor="start"
@@ -47,7 +47,7 @@ def temporal_train_test_split(
     )
 
 
-# todo 0.37.0 - check whether we should remove, otherwise bump
+# todo 0.38.0 - check whether we should remove, otherwise bump
 # still used in blog posts and old tutorials
 def ExpandingWindowSplitter(fh=1, initial_window=10, step_length=1):
     """Legacy export of Expanding window splitter.
@@ -70,7 +70,7 @@ def ExpandingWindowSplitter(fh=1, initial_window=10, step_length=1):
     return _EWSplitter(fh=fh, initial_window=initial_window, step_length=step_length)
 
 
-# todo 0.37.0 - check whether we should remove, otherwise bump
+# todo 0.38.0 - check whether we should remove, otherwise bump
 # still used in blog posts and old tutorials
 def SlidingWindowSplitter(
     fh=1, window_length=10, step_length=1, initial_window=None, start_with_window=True
diff --git a/sktime/forecasting/model_selection/_tune.py b/sktime/forecasting/model_selection/_tune.py
index 786f136ee..f9133ff8f 100644
--- a/sktime/forecasting/model_selection/_tune.py
+++ b/sktime/forecasting/model_selection/_tune.py
@@ -84,7 +84,7 @@ class BaseGridSearch(_DelegatedForecaster):
         if tune_by_variable:
             self.set_tags(**{"scitype:y": "univariate"})
 
-        # todo 0.37.0: check if this is still necessary
+        # todo 0.38.0: check if this is still necessary
         # n_jobs is deprecated, left due to use in tutorials, books, blog posts
         if n_jobs != "deprecated":
             warn(
diff --git a/sktime/forecasting/timesfm_forecaster.py b/sktime/forecasting/timesfm_forecaster.py
index f0a3ca1fa..05e644d8c 100644
--- a/sktime/forecasting/timesfm_forecaster.py
+++ b/sktime/forecasting/timesfm_forecaster.py
@@ -222,7 +222,7 @@ class TimesFMForecaster(_BaseGlobalForecaster):
         if not self.ignore_deps:
             if self.use_source_package:
                 # Use timesfm with a version bound if use_source_package is True
-                # todo 0.37.0: Regularly check whether timesfm version can be updated
+                # todo 0.38.0: Regularly check whether timesfm version can be updated
                 # if changed, also needs to be changed in docstring
                 self.set_tags(python_dependencies=["timesfm<1.2.0"])
         else:
diff --git a/sktime/transformations/series/clasp.py b/sktime/transformations/series/clasp.py
index 18d3416c5..bdb1e1e81 100644
--- a/sktime/transformations/series/clasp.py
+++ b/sktime/transformations/series/clasp.py
@@ -48,7 +48,7 @@ class ClaSPTransformer(BaseTransformer):
     Examples
     --------
     >>> from sktime.transformations.series.clasp import ClaSPTransformer
-    >>> from sktime.annotation.clasp import find_dominant_window_sizes
+    >>> from sktime.detection.clasp import find_dominant_window_sizes
     >>> from sktime.datasets import load_electric_devices_segmentation
     >>> X, true_period_size, true_cps = load_electric_devices_segmentation()
     >>> dominant_period_size = find_dominant_window_sizes(X) # doctest: +SKIP


Test patch:
diff --git a/sktime/datatypes/tests/test_lookup.py b/sktime/datatypes/tests/test_lookup.py
index bc4120011..7f2b34c04 100644
--- a/sktime/datatypes/tests/test_lookup.py
+++ b/sktime/datatypes/tests/test_lookup.py
@@ -2,20 +2,28 @@
 
 __author__ = ["fkiraly"]
 
-import pytest
-
 from sktime.datatypes._registry import (
-    MTYPE_REGISTER,
     MTYPE_SOFT_DEPS,
+    generate_mtype_register,
     mtype_to_scitype,
     scitype_to_mtype,
 )
 from sktime.utils.dependencies import _check_soft_dependencies
 
-MTYPE_SCITYPE_PAIRS = [(k[0], k[1]) for k in MTYPE_REGISTER]
+
+def pytest_generate_tests(metafunc):
+    register = generate_mtype_register()
+    if "mtype" in metafunc.fixturenames and "scitype" in metafunc.fixturenames:
+        mtypes_scitypes = [(k[0], k[1]) for k in register]
+        metafunc.parametrize("mtype, scitype", mtypes_scitypes)
+    elif "mtype" in metafunc.fixturenames:
+        mtypes = [k[0] for k in register]
+        metafunc.parametrize("mtype", mtypes)
+    elif "scitype" in metafunc.fixturenames:
+        scitypes = [k[1] for k in register]
+        metafunc.parametrize("scitype", scitypes)
 
 
-@pytest.mark.parametrize("mtype, scitype", MTYPE_SCITYPE_PAIRS)
 def test_mtype_to_scitype(mtype, scitype):
     """Tests that mtype_to_scitype yields the correct output for a string.
 
@@ -50,6 +58,7 @@ def test_mtype_to_scitype_list():
     AssertionError mtype_to_scitype does not convert mtype to scitype
     Exception if any is raised by mtype_to_scitype
     """
+    MTYPE_REGISTER = generate_mtype_register()
     mtype_list = [k[0] for k in MTYPE_REGISTER]
     expected_scitype_list = [k[1] for k in MTYPE_REGISTER]
     result = mtype_to_scitype(mtype_list)
@@ -59,7 +68,6 @@ def test_mtype_to_scitype_list():
     assert result == expected_scitype_list, msg
 
 
-@pytest.mark.parametrize("mtype, scitype", MTYPE_SCITYPE_PAIRS)
 def test_scitype_to_mtype(mtype, scitype):
     """Tests that scitype_to_mtype yields the correct output for a string.
 
diff --git a/sktime/detection/tests/test_plotting.py b/sktime/detection/tests/test_plotting.py
index c2ad301e1..3942968cd 100644
--- a/sktime/detection/tests/test_plotting.py
+++ b/sktime/detection/tests/test_plotting.py
@@ -2,7 +2,7 @@ import numpy as np
 import pandas as pd
 import pytest
 
-from sktime.annotation.plotting.utils import (
+from sktime.detection.plotting.utils import (
     plot_time_series_with_change_points,
     plot_time_series_with_profiles,
 )
diff --git a/sktime/forecasting/base/tests/test_fh.py b/sktime/forecasting/base/tests/test_fh.py
index 2e7359222..1fc1b68a5 100644
--- a/sktime/forecasting/base/tests/test_fh.py
+++ b/sktime/forecasting/base/tests/test_fh.py
@@ -745,7 +745,7 @@ def test_exponential_smoothing_case_with_naive():
 
 
 # TODO: Replace this long running test with fast unit test
-# todo 0.37.0: check whether numpy 2 bound is still necessary
+# todo 0.38.0: check whether numpy 2 bound is still necessary
 @pytest.mark.skipif(
     not run_test_module_changed(["sktime.forecasting.base", "sktime.datatypes"])
     or not _check_estimator_deps(AutoARIMA, severity="none")
diff --git a/sktime/forecasting/compose/tests/test_hierarchy_ensemble.py b/sktime/forecasting/compose/tests/test_hierarchy_ensemble.py
index bc3d2342d..1af6d2421 100644
--- a/sktime/forecasting/compose/tests/test_hierarchy_ensemble.py
+++ b/sktime/forecasting/compose/tests/test_hierarchy_ensemble.py
@@ -49,14 +49,14 @@ def test_hierarchy_ensemble_level_predict(forecasters):
 
     for i in range(len(forecasters)):
         test_frcstr = forecasters[i][1].clone()
-        df = y[y.index.droplevel(-1).isin(forecaster.fitted_list[i][1])]
+        df = y[y.index.droplevel(-1).isin(forecaster.fitted_list_[i][1])]
         test_frcstr.fit(df, fh=[1, 2, 3])
         test_pred = test_frcstr.predict()
         msg = "Level predictions do not match"
         assert np.all(actual_pred.loc[test_pred.index] == test_pred), msg
 
     def_frcstr = forecasters[0][1].clone()
-    df = y[y.index.droplevel(-1).isin(forecaster.fitted_list[-1][1])]
+    df = y[y.index.droplevel(-1).isin(forecaster.fitted_list_[-1][1])]
     def_frcstr.fit(df, fh=[1, 2, 3])
     def_pred = def_frcstr.predict()
     msg = "Level default predictions do not match"
@@ -99,14 +99,14 @@ def test_hierarchy_ensemble_level_predict_parallel(forecasters):
 
     for i in range(len(forecasters)):
         test_frcstr = forecasters[i][1].clone()
-        df = y[y.index.droplevel(-1).isin(forecaster.fitted_list[i][1])]
+        df = y[y.index.droplevel(-1).isin(forecaster.fitted_list_[i][1])]
         test_frcstr.fit(df, fh=[1, 2, 3])
         test_pred = test_frcstr.predict()
         msg = "Level predictions do not match"
         assert np.all(actual_pred.loc[test_pred.index] == test_pred), msg
 
     def_frcstr = forecasters[0][1].clone()
-    df = y[y.index.droplevel(-1).isin(forecaster.fitted_list[-1][1])]
+    df = y[y.index.droplevel(-1).isin(forecaster.fitted_list_[-1][1])]
     def_frcstr.fit(df, fh=[1, 2, 3])
     def_pred = def_frcstr.predict()
     msg = "Level default predictions do not match"
@@ -152,14 +152,14 @@ def test_hierarchy_ensemble_node_predict_parallel(forecasters):
 
     for i in range(len(forecasters)):
         test_frcstr = forecasters[i][1].clone()
-        df = y[y.index.droplevel(-1).isin(forecaster.fitted_list[i][1])]
+        df = y[y.index.droplevel(-1).isin(forecaster.fitted_list_[i][1])]
         test_frcstr.fit(df, fh=[1, 2, 3])
         test_pred = test_frcstr.predict()
         msg = "Node predictions do not match"
         assert np.all(actual_pred.loc[test_pred.index] == test_pred), msg
 
     def_frcstr = forecasters[0][1].clone()
-    df = y[y.index.droplevel(-1).isin(forecaster.fitted_list[-1][1])]
+    df = y[y.index.droplevel(-1).isin(forecaster.fitted_list_[-1][1])]
     def_frcstr.fit(df, fh=[1, 2, 3])
     def_pred = def_frcstr.predict()
     msg = "Node default predictions do not match"
@@ -201,14 +201,14 @@ def test_hierarchy_ensemble_node_predict(forecasters):
 
     for i in range(len(forecasters)):
         test_frcstr = forecasters[i][1].clone()
-        df = y[y.index.droplevel(-1).isin(forecaster.fitted_list[i][1])]
+        df = y[y.index.droplevel(-1).isin(forecaster.fitted_list_[i][1])]
         test_frcstr.fit(df, fh=[1, 2, 3])
         test_pred = test_frcstr.predict()
         msg = "Node predictions do not match"
         assert np.all(actual_pred.loc[test_pred.index] == test_pred), msg
 
     def_frcstr = forecasters[0][1].clone()
-    df = y[y.index.droplevel(-1).isin(forecaster.fitted_list[-1][1])]
+    df = y[y.index.droplevel(-1).isin(forecaster.fitted_list_[-1][1])]
     def_frcstr.fit(df, fh=[1, 2, 3])
     def_pred = def_frcstr.predict()
     msg = "Node default predictions do not match"
@@ -300,7 +300,7 @@ def test_level_one_data(forecasters, default):
 
     for i in range(len(forecasters)):
         test_frcstr = forecasters[i][1].clone()
-        df = y[y.index.droplevel(-1).isin(forecaster.fitted_list[i][1])]
+        df = y[y.index.droplevel(-1).isin(forecaster.fitted_list_[i][1])]
         test_frcstr.fit(df, fh=[1, 2, 3])
         test_pred = test_frcstr.predict()
         msg = "Node predictions do not match"
@@ -310,7 +310,7 @@ def test_level_one_data(forecasters, default):
     nodes = set(flatten(nodes))
     if default is not None and len(nodes) != len(y.index.droplevel(-1).unique()):
         def_frcstr = default
-        df = y[y.index.droplevel(-1).isin(forecaster.fitted_list[-1][1])]
+        df = y[y.index.droplevel(-1).isin(forecaster.fitted_list_[-1][1])]
         def_frcstr.fit(df, fh=[1, 2, 3])
         def_pred = def_frcstr.predict()
         msg = "Node default predictions do not match"
diff --git a/sktime/registry/tests/test_lookup.py b/sktime/registry/tests/test_lookup.py
index f0f4c95ac..9b20de9a9 100644
--- a/sktime/registry/tests/test_lookup.py
+++ b/sktime/registry/tests/test_lookup.py
@@ -248,10 +248,9 @@ def test_scitype_inference(estimator_scitype):
     inferred_scitype = all_scitypes[0]
 
     # stepout for detector due to rename in scitype
-    # todo 0.37.0 - replace "detector" with "series-annotator"
     # todo 1.0.0 - remove this stepout entirely
-    if estimator_scitype == "detector":
-        assert "detector" in all_scitypes
+    if estimator_scitype == "series-annotator":
+        assert "series-annotator" in all_scitypes
         return None
 
     assert inferred_scitype == estimator_scitype, (
diff --git a/sktime/tests/_config.py b/sktime/tests/_config.py
index b1ca27442..3790bd551 100644
--- a/sktime/tests/_config.py
+++ b/sktime/tests/_config.py
@@ -72,6 +72,7 @@ EXCLUDE_ESTIMATORS = [
     # multiple timeouts and sporadic failures reported related to VARMAX
     # 2997, 3176, 7985
     "VARMAX",
+    "SCINetForecaster",  # known bug #7871
 ]
 
 
diff --git a/sktime/utils/_testing/detection.py b/sktime/utils/_testing/detection.py
index 531b7cddd..a5ed8a4ed 100644
--- a/sktime/utils/_testing/detection.py
+++ b/sktime/utils/_testing/detection.py
@@ -3,7 +3,7 @@ __all__ = []
 
 from sklearn.utils import check_random_state
 
-from sktime.annotation.datagen import piecewise_poisson
+from sktime.detection.datagen import piecewise_poisson
 from sktime.utils._testing.series import _make_series