Repository: sktime/sktime

Issue:
[ENH] rename `"series-annotator"` scitype to `"detector"`
In line with the general rationale of https://github.com/sktime/sktime/issues/7295, we should rename the `"series-annotator"` scitype to `"detector"`.

To ensure downwards compatibility though, it is best to simply *add* the `"detector"` scitype in the list of scitypes (turning str into a list ot str), in the tag `object_type`. This will ensure that queries using the old name will still work, while queries with the new name start working, allowing us to transition to using the latter, new queries in tutorials, primary internal access patterns, etc.

Discussion:
jgyfutub: @fkiraly thanks for your review! I did all the changes as you requested .Please review the changes.
jgyfutub: @fkiraly can you please check my changes and review it , It has been a long time since I got review after I made changes.Thanks!
fkiraly: @jgyfutub, thank you for your help! I will now take over this PR to unblock further work on top of it, as previously mentioned.

Patch:
diff --git a/.all-contributorsrc b/.all-contributorsrc
index 153782caa..f48ba9a42 100644
--- a/.all-contributorsrc
+++ b/.all-contributorsrc
@@ -3174,6 +3174,15 @@
         "code"
       ]
     },
+    {
+      "login": "jgyfutub",
+      "name": "Vedant Pandey",
+      "avatar_url": "https://avatars.githubusercontent.com/u/97391064?s=400&v=4",
+      "profile": "https://github.com/jgyfutub",
+      "contributions": [
+        "code"
+      ]
+    },
     {
       "login": "manolotis",
       "name": "Manuel Muñoz Sánchez",
@@ -3182,7 +3191,6 @@
       "contributions": [
         "doc"
       ]
-     }
-
+    }
   ]
 }
diff --git a/docs/source/api_reference/data_format.rst b/docs/source/api_reference/data_format.rst
index 6d42cd3a6..4f2329996 100644
--- a/docs/source/api_reference/data_format.rst
+++ b/docs/source/api_reference/data_format.rst
@@ -76,6 +76,10 @@ The ``Series`` mtype represents a single time series.
 
 .. currentmodule:: sktime.datatypes._series._check
 
+.. autosummary::
+    :toctree: auto_generated/
+    :template: class.rst
+
     SeriesPdDataFrame
     SeriesPdSeries
     SeriesNp2D
@@ -93,6 +97,10 @@ The ``Panel`` mtype represents a flat collection of time series.
 
 .. currentmodule:: sktime.datatypes._panel._check
 
+.. autosummary::
+    :toctree: auto_generated/
+    :template: class.rst
+
     PanelPdMultiIndex
     PanelNp3D
     PanelDfList
@@ -109,6 +117,10 @@ The ``Hierarchical`` mtype represents a hierarchical collection of time series.
 
 .. currentmodule:: sktime.datatypes._hierarchical._check
 
+.. autosummary::
+    :toctree: auto_generated/
+    :template: class.rst
+
     HierarchicalPdMultiIndex
     HierarchicalDask
     HierarchicalPolarsEager
@@ -121,6 +133,10 @@ The ``Table`` mtype represents a (non-temporal) data frame table.
 
 .. currentmodule:: sktime.datatypes._table._check
 
+.. autosummary::
+    :toctree: auto_generated/
+    :template: class.rst
+
     TablePdDataFrame
     TablePdSeries
     TableNp1D
diff --git a/sktime/datatypes/_table/_base.py b/sktime/datatypes/_table/_base.py
index 0c12cfa7c..4742704e1 100644
--- a/sktime/datatypes/_table/_base.py
+++ b/sktime/datatypes/_table/_base.py
@@ -6,8 +6,8 @@ __author__ = ["fkiraly"]
 from sktime.datatypes._base import BaseDatatype
 
 
-class BaseTable(BaseDatatype):
-    """Base class for Table data types.
+class ScitypeTable(BaseDatatype):
+    """Data Frame or Table data type.
 
     Parameters
     ----------
diff --git a/sktime/datatypes/_table/_check.py b/sktime/datatypes/_table/_check.py
index a6e7c7872..4517e7338 100644
--- a/sktime/datatypes/_table/_check.py
+++ b/sktime/datatypes/_table/_check.py
@@ -39,12 +39,12 @@ import pandas as pd
 
 from sktime.datatypes._base._common import _req, _ret
 from sktime.datatypes._dtypekind import _get_feature_kind, _get_table_dtypekind
-from sktime.datatypes._table._base import BaseTable
+from sktime.datatypes._table._base import ScitypeTable
 
 PRIMITIVE_TYPES = (float, int, str)
 
 
-class TablePdDataFrame(BaseTable):
+class TablePdDataFrame(ScitypeTable):
     """Data type: pandas.DataFrame based specification of data frame table.
 
     Parameters are inferred by check.
@@ -138,7 +138,7 @@ def _check_pddataframe_table(obj, return_metadata=False, var_name="obj"):
     return _ret(True, None, metadata, return_metadata)
 
 
-class TablePdSeries(BaseTable):
+class TablePdSeries(ScitypeTable):
     """Data type: pandas.Series based specification of data frame table.
 
     Parameters are inferred by check.
@@ -237,7 +237,7 @@ def _check_pdseries_table(obj, return_metadata=False, var_name="obj"):
     return _ret(True, None, metadata, return_metadata)
 
 
-class TableNp1D(BaseTable):
+class TableNp1D(ScitypeTable):
     """Data type: 1D np.ndarray based specification of data frame table.
 
     Parameters are inferred by check.
@@ -336,7 +336,7 @@ def _check_numpy1d_table(obj, return_metadata=False, var_name="obj"):
     return _ret(True, None, metadata, return_metadata)
 
 
-class TableNp2D(BaseTable):
+class TableNp2D(ScitypeTable):
     """Data type: 2D np.ndarray based specification of data frame table.
 
     Parameters are inferred by check.
@@ -434,7 +434,7 @@ def _check_numpy2d_table(obj, return_metadata=False, var_name="obj"):
     return _ret(True, None, metadata, return_metadata)
 
 
-class TableListOfDict(BaseTable):
+class TableListOfDict(ScitypeTable):
     """Data type: list of dict based specification of data frame table.
 
     Parameters are inferred by check.
@@ -555,7 +555,7 @@ def _check_list_of_dict_table(obj, return_metadata=False, var_name="obj"):
     return _ret(True, None, metadata, return_metadata)
 
 
-class TablePolarsEager(BaseTable):
+class TablePolarsEager(ScitypeTable):
     """Data type: eager polars DataFrame based specification of data frame table.
 
     Parameters are inferred by check.
@@ -620,7 +620,7 @@ class TablePolarsEager(BaseTable):
         return check_polars_frame(obj, return_metadata, var_name, lazy=False)
 
 
-class TablePolarsLazy(BaseTable):
+class TablePolarsLazy(ScitypeTable):
     """Data type: lazy polars DataFrame based specification of data frame table.
 
     Parameters are inferred by check.
diff --git a/sktime/detection/base/_base.py b/sktime/detection/base/_base.py
index a85d441c1..c18f1d3f2 100644
--- a/sktime/detection/base/_base.py
+++ b/sktime/detection/base/_base.py
@@ -65,7 +65,9 @@ class BaseDetector(BaseEstimator):
     """
 
     _tags = {
-        "object_type": "series-annotator",  # type of object
+        # 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
         "learning_type": "None",  # Tag to determine test in test_all_annotators
         "task": "None",  # Tag to determine test in test_all_annotators
         #
diff --git a/sktime/registry/_base_classes.py b/sktime/registry/_base_classes.py
index 4ac44c56e..d9b49249b 100644
--- a/sktime/registry/_base_classes.py
+++ b/sktime/registry/_base_classes.py
@@ -261,12 +261,12 @@ class regressor(_BaseScitypeOfObject):
         return BaseRegressor
 
 
-class series_annotator(_BaseScitypeOfObject):
-    """Time series annotator."""
+class detector(_BaseScitypeOfObject):
+    """Detector of anomalies, outliers, or change points."""
 
     _tags = {
-        "scitype_name": "series-annotator",
-        "short_descr": "time series annotator",
+        "scitype_name": "detector",
+        "short_descr": "detector - anomalies, outliers, change points",
         "parent_scitype": "estimator",
     }
 
@@ -519,6 +519,26 @@ def get_base_class_lookup(mixin=False, include_baseobjs=True):
     return base_class_lookup
 
 
+# LEGACY types - remove in 1.0.0
+# ------------------------------
+
+
+class series_annotator(_BaseScitypeOfObject):
+    """Time series annotator."""
+
+    _tags = {
+        "scitype_name": "series-annotator",
+        "short_descr": "detector - anomalies, outliers, change points",
+        "parent_scitype": "estimator",
+    }
+
+    @classmethod
+    def get_base_class(cls):
+        from sktime.detection.base import BaseDetector
+
+        return BaseDetector
+
+
 class transformer_series_to_primitives(_BaseScitypeOfObject):
     """LEGACY - time series to primitives transformer."""
 
diff --git a/sktime/registry/_scitype_coercion.py b/sktime/registry/_scitype_coercion.py
index dfbf2fa71..2374661e3 100644
--- a/sktime/registry/_scitype_coercion.py
+++ b/sktime/registry/_scitype_coercion.py
@@ -22,11 +22,15 @@ def _coerce_series_annotator_to_transformer(obj):
     return AnnotatorAsTransformer(obj)
 
 
+# todo 1.0.0 - remove series-annotator
 _coerce_register[("series-annotator", "transformer")] = (
     _coerce_series_annotator_to_transformer
 )
 
 
+_coerce_register[("detector", "transformer")] = _coerce_series_annotator_to_transformer
+
+
 def _coerce_clusterer_to_transformer(obj):
     from sktime.clustering.compose import ClustererAsTransformer
 
diff --git a/sktime/registry/_tags.py b/sktime/registry/_tags.py
index 1eddff7b0..2ba57f918 100644
--- a/sktime/registry/_tags.py
+++ b/sktime/registry/_tags.py
@@ -1830,13 +1830,13 @@ ESTIMATOR_TAG_REGISTER = [
     ),
     (
         "task",
-        "series-annotator",
+        "detector",
         "str",
         "subtype of series annotator, e.g., 'anomaly_detection', 'segmentation'",
     ),
     (
         "learning_type",
-        "series-annotator",
+        "detector",
         "str",
         "type of learning, e.g., 'supervised', 'unsupervised'",
     ),


Test patch:
diff --git a/sktime/annotation/tests/test_all_annotators.py b/sktime/annotation/tests/test_all_annotators.py
index 9c5acc093..a4d9a212a 100644
--- a/sktime/annotation/tests/test_all_annotators.py
+++ b/sktime/annotation/tests/test_all_annotators.py
@@ -29,7 +29,7 @@ class AnnotatorsFixtureGenerator(BaseFixtureGenerator):
     #   additional fixtures, parameters, etc should be added here
     #   TestAllAnnotators should contain the tests only
 
-    estimator_type_filter = "series-annotator"
+    estimator_type_filter = "detector"
 
 
 class TestAllAnnotators(AnnotatorsFixtureGenerator, QuickTester):
diff --git a/sktime/registry/tests/test_lookup.py b/sktime/registry/tests/test_lookup.py
index e192d9311..96ebd776f 100644
--- a/sktime/registry/tests/test_lookup.py
+++ b/sktime/registry/tests/test_lookup.py
@@ -239,7 +239,15 @@ def test_all_estimators_tag_filter(pred_int):
 def test_scitype_inference(estimator_scitype):
     """Check that scitype inverts _check_estimator_types."""
     base_class = _check_estimator_types(estimator_scitype)[0]
-    inferred_scitype = scitype(base_class)
+    all_scitypes = scitype(base_class, force_single_scitype=False, coerce_to_list=True)
+    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
+        return None
 
     assert (
         inferred_scitype == estimator_scitype
diff --git a/sktime/tests/test_class_register.py b/sktime/tests/test_class_register.py
index 461e55268..8f1f57a73 100644
--- a/sktime/tests/test_class_register.py
+++ b/sktime/tests/test_class_register.py
@@ -54,12 +54,14 @@ def get_test_class_registry():
     # so also imply estimator and object tests, or only object tests
     testclass_dict["aligner"] = TestAllAligners
     testclass_dict["classifier"] = TestAllClassifiers
+    testclass_dict["detector"] = TestAllAnnotators
     testclass_dict["distribution"] = TestAllDistributions
     testclass_dict["early_classifier"] = TestAllEarlyClassifiers
     testclass_dict["forecaster"] = TestAllForecasters
     testclass_dict["global_forecaster"] = TestAllGlobalForecasters
     testclass_dict["param_est"] = TestAllParamFitters
     testclass_dict["regressor"] = TestAllRegressors
+    # todo 1.0.0 - remove series-annotator
     testclass_dict["series-annotator"] = TestAllAnnotators
     testclass_dict["splitter"] = TestAllSplitters
     testclass_dict["transformer"] = TestAllTransformers