Repository: aeon-toolkit/aeon
Pull request #1672 (2024-06-14 18:45:55)

[DEP] make BoxCox legacy
move boxcox to legacy, to embedded to untangle

part of #1393 

review-notebook-app[bot]: Check out this pull request on&nbsp; <a href="https://app.reviewnb.com/aeon-toolkit/aeon/pull/1672"><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>
aeon-actions-bot[bot]: 
## Thank you for contributing to `aeon`

I did not find any labels to add based on the title. Please add the [ENH], [MNT], [BUG], [DOC], [REF], [DEP] and/or [GOV] tags to your pull requests titles. For now you can add the labels manually.


The [Checks](https://github.com/aeon-toolkit/aeon/pull/1672/checks) tab will show the status of our automated tests. You can click on individual test runs in the tab or "Details" in the panel below to see more information if there is a failure.

If our `pre-commit` code quality check fails, any trivial fixes will automatically be pushed to your PR unless it is a draft.

Don't hesitate to ask questions on the `aeon` [Slack](https://join.slack.com/t/aeon-toolkit/shared_invite/zt-22vwvut29-HDpCu~7VBUozyfL_8j3dLA) channel if you have any.

### PR CI actions

These checkboxes will add labels to enable/disable CI functionality for this PR. This may not take effect immediately, and a new commit may be required to run the new configuration.

- [ ] Run `pre-commit` checks for all files
- [ ] Run all `pytest` tests and configurations
- [ ] Run all notebook example tests
- [ ] Run numba-disabled `codecov` tests
- [ ] Stop automatic `pre-commit` fixes (always disabled for drafts)
    

Patch:
diff --git a/aeon/forecasting/compose/_pipeline.py b/aeon/forecasting/compose/_pipeline.py
index 1e001dd9..825d8512 100644
--- a/aeon/forecasting/compose/_pipeline.py
+++ b/aeon/forecasting/compose/_pipeline.py
@@ -761,8 +761,7 @@ class TransformedTargetForecaster(_Pipeline):
     ...     ("detrender", Detrender()),
     ...     ("forecaster", NaiveForecaster(strategy="drift")),
     ... ])
-    >>> pipe.fit(y)
-    TransformedTargetForecaster(...)
+    >>> t = pipe.fit(y)
     >>> y_pred = pipe.predict(fh=[1,2,3])
 
         Example 2: without strings
@@ -1558,7 +1557,7 @@ class Permute(_DelegatedForecaster, BaseForecaster, _HeterogenousMetaEstimator):
     >>> from aeon.forecasting.base import ForecastingHorizon
     >>> from aeon.forecasting.compose import ForecastingPipeline, Permute
     >>> from aeon.forecasting.naive import NaiveForecaster
-    >>> from aeon.transformations.boxcox import BoxCoxTransformer
+    >>> from aeon.transformations.series._boxcox import BoxCoxTransformer
     >>> from aeon.transformations.exponent import ExponentTransformer
 
     Simple example: permute sequence of estimator in forecasting pipeline
diff --git a/aeon/transformations/_legacy/__init__.py b/aeon/transformations/_legacy/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/aeon/transformations/boxcox.py b/aeon/transformations/_legacy/_boxcox.py
similarity index 91%
rename from aeon/transformations/boxcox.py
rename to aeon/transformations/_legacy/_boxcox.py
index 5a898423..420d0b86 100644
--- a/aeon/transformations/boxcox.py
+++ b/aeon/transformations/_legacy/_boxcox.py
@@ -1,10 +1,9 @@
 """Implemenents Box-Cox and Log Transformations."""
 
 __maintainer__ = []
-__all__ = ["BoxCoxTransformer", "LogTransformer"]
+__all__ = ["_BoxCoxTransformer", "_LogTransformer"]
 
 import numpy as np
-from deprecated.sphinx import deprecated
 from scipy import optimize, special, stats
 from scipy.special import boxcox, inv_boxcox
 from scipy.stats import boxcox_llf, distributions, variation
@@ -41,21 +40,14 @@ def _calc_uniform_order_statistic_medians(n):
     return v
 
 
-# TODO: remove in v0.10.0
-@deprecated(
-    version="0.9.0",
-    reason="BoxCoxTransformer will be removed in version 0.10.0 and replaced with a "
-    "BaseSeriesTransformer version in the transformations.series module.",
-    category=FutureWarning,
-)
-class BoxCoxTransformer(BaseTransformer):
+class _BoxCoxTransformer(BaseTransformer):
     r"""Box-Cox power transform.
 
     Box-Cox transformation is a power transformation that is used to
     make data more normally distributed and stabilize its variance based
     on the hyperparameter lambda. [1]_
 
-    The BoxCoxTransformer solves for the lambda parameter used in the Box-Cox
+    The _BoxCoxTransformer solves for the lambda parameter used in the Box-Cox
     transformation given `method`, the optimization approach, and input
     data provided to `fit`. The use of Guerrero's method for solving for lambda
     requires the seasonal periodicity, `sp` be provided. [2]_
@@ -88,7 +80,7 @@ class BoxCoxTransformer(BaseTransformer):
 
     See Also
     --------
-    LogTransformer :
+    _LogTransformer :
         Transformer input data using natural log. Can help normalize data and
         compress variance of the series.
     aeon.transformations.exponent.ExponentTransformer :
@@ -113,14 +105,6 @@ class BoxCoxTransformer(BaseTransformer):
        Journal ofthe Royal Statistical Society, Series B, 26, 211-252.
     .. [2] V.M. Guerrero, "Time-series analysis supported by Power
        Transformations ", Journal of Forecasting, vol. 12, pp. 37-48, 1993.
-
-    Examples
-    --------
-    >>> from aeon.transformations.boxcox import BoxCoxTransformer
-    >>> from aeon.datasets import load_airline
-    >>> y = load_airline()
-    >>> transformer = BoxCoxTransformer()
-    >>> y_hat = transformer.fit_transform(y)
     """
 
     _tags = {
@@ -214,14 +198,7 @@ class BoxCoxTransformer(BaseTransformer):
         return Xt
 
 
-# TODO: remove in v0.10.0
-@deprecated(
-    version="0.9.0",
-    reason="LogTransformer will be removed in version 0.10.0 and replaced with a "
-    "BaseSeriesTransformer version in the transformations.series module.",
-    category=FutureWarning,
-)
-class LogTransformer(BaseTransformer):
+class _LogTransformer(BaseTransformer):
     """Natural logarithm transformation.
 
     The Natural logarithm transformation can be used to make the data more normally
@@ -238,7 +215,7 @@ class LogTransformer(BaseTransformer):
 
     See Also
     --------
-    BoxCoxTransformer :
+    _BoxCoxTransformer :
         Applies Box-Cox power transformation. Can help normalize data and
         compress variance of the series.
     aeon.transformations.exponent.ExponentTransformer :
@@ -251,14 +228,6 @@ class LogTransformer(BaseTransformer):
     Notes
     -----
     The log transformation is applied as :math:`ln(y)`.
-
-    Examples
-    --------
-    >>> from aeon.transformations.boxcox import LogTransformer
-    >>> from aeon.datasets import load_airline
-    >>> y = load_airline()
-    >>> transformer = LogTransformer()
-    >>> y_hat = transformer.fit_transform(y)
     """
 
     _tags = {
diff --git a/aeon/transformations/_legacy/tests/__init__.py b/aeon/transformations/_legacy/tests/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/aeon/transformations/adapt.py b/aeon/transformations/adapt.py
index 7489a8be..33a93a39 100644
--- a/aeon/transformations/adapt.py
+++ b/aeon/transformations/adapt.py
@@ -223,7 +223,7 @@ class TabularToSeriesAdaptor(BaseTransformer):
 # TODO: remove in v0.11.0
 @deprecated(
     version="0.10.0",
-    reason="PandasTransformAdaptorwill be removed in version 0.11.0.",
+    reason="PandasTransformAdaptor will be removed in version 0.11.0.",
     category=FutureWarning,
 )
 class PandasTransformAdaptor(BaseTransformer):
diff --git a/aeon/transformations/bootstrap/_mbb.py b/aeon/transformations/bootstrap/_mbb.py
index 8bb2929c..f889f22b 100644
--- a/aeon/transformations/bootstrap/_mbb.py
+++ b/aeon/transformations/bootstrap/_mbb.py
@@ -7,12 +7,19 @@ from typing import Tuple, Union
 
 import numpy as np
 import pandas as pd
+from deprecated.sphinx import deprecated
 from sklearn.utils import check_random_state
 
+from aeon.transformations._legacy._boxcox import _BoxCoxTransformer
 from aeon.transformations.base import BaseTransformer
-from aeon.transformations.boxcox import BoxCoxTransformer
 
 
+# TODO: remove in v0.11.0
+@deprecated(
+    version="0.10.0",
+    reason="STLBootstrapTransformer will be removed in version 0.11.0.",
+    category=FutureWarning,
+)
 class STLBootstrapTransformer(BaseTransformer):
     """Creates a population of similar time series.
 
@@ -265,7 +272,7 @@ class STLBootstrapTransformer(BaseTransformer):
         )
 
         # fit boxcox to get lambda and transform X
-        self.box_cox_transformer_ = BoxCoxTransformer(
+        self.box_cox_transformer_ = _BoxCoxTransformer(
             sp=self.sp, bounds=self.lambda_bounds, method=self.lambda_method
         )
         self.box_cox_transformer_.fit(X)
@@ -399,6 +406,12 @@ class STLBootstrapTransformer(BaseTransformer):
         return params
 
 
+# TODO: remove in v0.11.0
+@deprecated(
+    version="0.10.0",
+    reason="MovingBlockBootstrapTransformer will be removed in version 0.11.0.",
+    category=FutureWarning,
+)
 class MovingBlockBootstrapTransformer(BaseTransformer):
     """Moving Block Bootstrapping method for synthetic time series generation.
 
diff --git a/aeon/transformations/clear_sky.py b/aeon/transformations/clear_sky.py
deleted file mode 100644
index 344fbb93..00000000
--- a/aeon/transformations/clear_sky.py
+++ /dev/null
@@ -1,370 +0,0 @@
-"""Clear sky transformer for solar time-series."""
-
-__maintainer__ = []
-
-import numpy as np
-import pandas as pd
-from deprecated.sphinx import deprecated
-from joblib import Parallel, delayed
-from scipy.stats import vonmises
-
-from aeon.transformations.base import BaseTransformer
-
-
-# TODO: remove in v0.10.0
-@deprecated(
-    version="0.9.0",
-    reason="ClearSky will be removed in version 0.10.0 and replaced with a "
-    "BaseSeriesTransformer version in the transformations.series module.",
-    category=FutureWarning,
-)
-class ClearSky(BaseTransformer):
-    """Clear sky transformer for solar data.
-
-    This is a transformation which converts a time series from it's original
-    domain into a percentage domain. The numerator at each time step in the
-    transformation is the input values, the denominator is a weighted
-    quantile of the time series for that particular time step. In the example
-    of solar power transformations, the denominator is an approximation of the
-    clear sky power, and the output of the transformation is the clearness index.
-
-    The clear sky power, i.e. the denominator, is calculated on a grid containing
-    each unique combination of time-of-day and day-of-year. The spacing of the
-    grid depends on the frequency of the input data.
-
-    The weights are defined using von-mises kernels with bandwidths chosen by the
-    user.
-
-    This transformation can be inacurate at low values, in the solar example during
-    early morning and late evening. Therefore, clear sky values below a threshold can
-    be fixed to zero in the transformed domain. Denominator values of zero are set
-    to zero in the transformed domain by default.
-
-    This transformer is based on the work detailed in [1]_.
-
-    Parameters
-    ----------
-    quantile_prob : float, default=0.95
-        The probability level used to calculate the weighted quantile
-    bw_diurnal : float, default=100
-        The bandwidth of the diurnal kernel. This is the kappa value of the
-        von mises kernel for time of day.
-    bw_annual : float, default=10
-        The bandwidth of the annual kernel. This is the kappa value of the
-        von mises kernel for day of year.
-    min_thresh : float, default=0
-        The threshold of the clear sky power below which values are
-        set to zero in the transformed domain.
-    n_jobs : int or None, default=None
-        Number of jobs to run in parallel.
-        None means 1 unless in a joblib.parallel_backend context.
-        -1 means using all processors.
-    backend : str, default="loky"
-        Specify the parallelisation backend implementation in joblib, where
-        "loky" is used by default.
-
-    References
-    ----------
-    .. [1] https://doi.org/10.1016/j.solener.2009.05.016
-
-    Examples
-    --------
-    >>> from aeon.transformations.clear_sky import ClearSky  # doctest: +SKIP
-    >>> from aeon.datasets import load_solar  # doctest: +SKIP
-    >>> y = load_solar()  # doctest: +SKIP
-    >>> transformer = ClearSky()  # doctest: +SKIP
-    >>> # takes ~1min
-    >>> y_trafo = transformer.fit_transform(y)  # doctest: +SKIP
-    """
-
-    _tags = {
-        "input_data_type": "Series",
-        "output_data_type": "Series",
-        "transform_labels": "None",
-        "instancewise": True,  # is this an instance-wise transform?
-        "capability:inverse_transform": True,  # can the transformer inverse transform?
-        "capability:multivariate": False,  # can the transformer handle multivariate X?
-        "X_inner_type": [
-            "pd.Series",
-        ],
-        "y_inner_type": "None",
-        "requires_y": False,  # does y need to be passed in fit?
-        "enforce_index_type": [
-            pd.DatetimeIndex,
-            pd.PeriodIndex,
-        ],  # index type that needs to be enforced in X/y
-        "fit_is_empty": False,  # is fit empty and can be skipped? Yes = True
-        "X-y-must-have-same-index": False,  # can estimator handle different X/y index?
-        "transform-returns-same-time-index": True,
-        "skip-inverse-transform": False,  # is inverse-transform skipped when called?
-        "capability:unequal_length": False,
-        "capability:unequal_length:removes": True,  # ?
-        "capability:missing_values": False,
-        "capability:missing_values:removes": True,
-        "python_version": None,  # PEP 440 python version specifier to limit versions
-        "python_dependencies": "statsmodels",
-    }
-
-    def __init__(
-        self,
-        quantile_prob=0.95,
-        bw_diurnal=100,
-        bw_annual=10,
-        min_thresh=0,
-        n_jobs=None,
-        backend="loky",
-    ):
-        self.quantile_prob = quantile_prob
-        self.bw_diurnal = bw_diurnal
-        self.bw_annual = bw_annual
-        self.min_thresh = min_thresh
-        self.n_jobs = n_jobs
-        self.backend = backend
-
-        super().__init__()
-
-    def _fit(self, X, y=None):
-        """Fit transformer to X and y.
-
-        private _fit containing the core logic, called from fit
-
-        Parameters
-        ----------
-        X : Series of pd.DataFrame
-            Data used to estimate the clear sky power.
-        y : Ignored argument for interface compatibility.
-
-        Returns
-        -------
-        self: reference to self
-        """
-        # check that the data is formatted correctly etc
-        self.freq = _check_index(X)
-        # now get grid of model
-        df = pd.DataFrame(index=X.index)
-        df["yday"] = df.index.dayofyear
-        df["tod"] = df.index.hour + df.index.minute / 60 + df.index.second / 60
-
-        # set up smoothing grid
-        tod = pd.timedelta_range(start="0T", end="1D", freq=self.freq)[:-1]
-        tod = [(x.total_seconds() / (60 * 60)) for x in tod.to_pytimedelta()]
-        yday = pd.RangeIndex(start=1, stop=367)
-        indx = pd.MultiIndex.from_product([yday, tod], names=["yday", "tod"])
-
-        # set up parallel function and backend
-        parallel = Parallel(n_jobs=self.n_jobs, backend=self.backend)
-
-        def par_csp(x):
-            res = _clearskypower(
-                y=X,
-                q=self.quantile_prob,
-                tod_i=x[1],
-                doy_i=x[0],
-                tod_vec=df["tod"],
-                doy_vec=df["yday"],
-                bw_tod=self.bw_diurnal,
-                bw_doy=self.bw_annual,
-            )
-
-            return res
-
-        # calculate the csp
-        csp = parallel(delayed(par_csp)(name) for name in indx)
-        csp = pd.Series(csp, index=indx, dtype="float64")
-        self.clearskypower = csp.sort_index()
-
-        return self
-
-    def _transform(self, X, y=None):
-        """Transform X and return a transformed version.
-
-        private _transform containing core logic, called from transform
-
-        Parameters
-        ----------
-        X : Series of pd.DataFrame
-            Data used to be transformed.
-        y : Ignored argument for interface compatibility.
-
-        Returns
-        -------
-        X_trafo : transformed version of X
-        """
-        _freq_ind = _check_index(X)
-        if self.freq != _freq_ind:
-            raise ValueError(
-                """
-                Change in frequency detected from original input. Make sure
-                X is the same frequency as used in .fit().
-                """
-            )
-        # get required seasonal index
-        yday = X.index.dayofyear
-        tod = X.index.hour + X.index.minute / 60 + X.index.second / 60
-        indx_seasonal = pd.MultiIndex.from_arrays([yday, tod], names=["yday", "tod"])
-
-        # look up values and overwrite index
-        csp = self.clearskypower[indx_seasonal].copy()
-        csp.index = X.index
-        X_trafo = X / csp
-
-        # threshold for small morning/evening values
-        X_trafo[(csp <= self.min_thresh) & (X.notnull())] = 0
-
-        return X_trafo
-
-    def _inverse_transform(self, X, y=None):
-        """Inverse transform, inverse operation to transform.
-
-        private _inverse_transform containing core logic, called from
-        inverse_transform
-
-        Parameters
-        ----------
-        X : Series of pd.DataFrame
-            Data used to be inversed transformed.
-        y : Ignored argument for interface compatibility.
-
-        Returns
-        -------
-        X_trafo : inverse transformed version of X
-        """
-        _freq_ind = _check_index(X)
-        if self.freq != _freq_ind:
-            raise ValueError(
-                """
-                Change in frequency detected from original input. Make sure
-                X is the same frequency as used in .fit().
-                """
-            )
-        yday = X.index.dayofyear
-        tod = X.index.hour + X.index.minute / 60 + X.index.second / 60
-        indx_seasonal = pd.MultiIndex.from_arrays([yday, tod], names=["yday", "tod"])
-
-        # look up values and overwrite index
-        csp = self.clearskypower[indx_seasonal].copy()
-        csp.index = X.index
-        X_trafo = X * csp
-
-        return X_trafo
-
-    def _get_fitted_params(self):
-        """Get fitted parameters.
-
-        Returns
-        -------
-        fitted_params : dict
-        """
-        params = {"clearskypower": self.clearskypower}
-
-        return params
-
-    @classmethod
-    def get_test_params(cls, parameter_set="default"):
-        """Return testing parameter settings for the estimator.
-
-        Parameters
-        ----------
-        parameter_set : str, default="default"
-            Name of the set of test parameters to return, for use in tests. If no
-            special parameters are defined for a value, will return `"default"` set.
-            There are currently no reserved values for transformers.
-
-        Returns
-        -------
-        params : dict or list of dict, default = {}
-            Parameters to create testing instances of the class
-            Each dict are parameters to construct an "interesting" test instance, i.e.,
-            `MyClass(**params)` or `MyClass(**params[i])` creates a valid test instance.
-            `create_test_instance` uses the first (or only) dictionary in `params`
-        """
-        params = {
-            "quantile_prob": 0.95,
-            "bw_diurnal": 100,
-            "bw_annual": 10,
-            "min_thresh": None,
-        }
-
-        return params
-
-
-def _clearskypower(y, q, tod_i, doy_i, tod_vec, doy_vec, bw_tod, bw_doy):
-    """Estimate the clear sky power for a given day-of-year and hour-of-day.
-
-    Parameters
-    ----------
-    y : Series of measurements
-    q : Probability level used for the quantile
-    tod_i : time-of-day of interest in hours
-    doy_i : day-of-year of interest in days
-    tod_vec : Series of time-of-day corresponding to the index of y
-    doy_vec: Series of day-of-year corresponding to the index of y
-    bw_tod : Kappa value used for defining weights for time-of-day
-    bw_doy : Kappa value used for defining weights for day-of-year
-
-    Returns
-    -------
-    csp : float
-        The clear sky power at tod_i and doy_i
-    """
-    from statsmodels.stats.weightstats import DescrStatsW
-
-    wts_tod = vonmises.pdf(
-        x=tod_i * 2 * np.pi / 24, kappa=bw_tod, loc=tod_vec * 2 * np.pi / 24
-    )
-    wts_doy = vonmises.pdf(
-        x=doy_i * 2 * np.pi / 365.25, kappa=bw_doy, loc=doy_vec * 2 * np.pi / 365.25
-    )
-
-    wts = wts_doy * wts_tod
-    wts = wts / wts.sum()
-
-    csp = DescrStatsW(y, weights=wts).quantile(probs=q).values[0]
-
-    return csp
-
-
-def _check_index(X):
-    """Check input value frequency is set and we have the correct index.
-
-    Parameters
-    ----------
-    X : Series or pd.DataFrame
-        Data used to be inversed transformed.
-
-    Raises
-    ------
-    ValueError : Input index must be class pd.DatetimeIndex or pd.PeriodIndex.
-    ValueError : Input index frequency cannot be inferred and is not set.
-    ValueError : Frequency of data not suitable for transformer as is.
-
-    Returns
-    -------
-    freq_ind : str or None
-        Frequency of data in string format
-
-    """
-    if not (isinstance(X.index, pd.DatetimeIndex)) | (
-        isinstance(X.index, pd.PeriodIndex)
-    ):
-        raise ValueError(
-            "Input index must be class pd.DatetimeIndex or pd.PeriodIndex."
-        )
-    # check that it has a frequency, if not infer
-    freq_ind = X.index.freq
-    if freq_ind is None:
-        freq_ind = pd.infer_freq(X.index)
-        if freq_ind is None:
-            raise ValueError("Input index frequency cannot be inferred and is not set.")
-
-    tod = pd.timedelta_range(start="0T", end="1D", freq=freq_ind)
-    # checck frequency of tod
-    if (tod.freq > pd.offsets.Day(1)) | (tod.freq < pd.offsets.Second(1)):
-        raise ValueError(
-            """
-            Transformer intended to be used with input frequency of greater than
-            or equal to one day and with a frequency of less or equal to than
-            1 second. Contributions welcome on adapting for these use cases.
-            """
-        )
-    return freq_ind
diff --git a/aeon/transformations/compose.py b/aeon/transformations/compose.py
index 444e3bc1..48db9d28 100644
--- a/aeon/transformations/compose.py
+++ b/aeon/transformations/compose.py
@@ -27,6 +27,7 @@ __all__ = [
     "TransformerPipeline",
     "YtoX",
 ]
+from aeon.transformations._legacy._boxcox import _BoxCoxTransformer
 from aeon.utils import ALL_TIME_SERIES_TYPES
 
 
@@ -746,11 +747,9 @@ class FitInTransform(BaseTransformer):
             `MyClass(**params)` or `MyClass(**params[i])` creates a valid test instance.
             `create_test_instance` uses the first (or only) dictionary in `params`
         """
-        from aeon.transformations.boxcox import BoxCoxTransformer
-
         params = [
-            {"transformer": BoxCoxTransformer()},
-            {"transformer": BoxCoxTransformer(), "skip_inverse_transform": False},
+            {"transformer": _BoxCoxTransformer()},
+            {"transformer": _BoxCoxTransformer(), "skip_inverse_transform": False},
         ]
         return params
 
@@ -1156,11 +1155,9 @@ class InvertTransform(_DelegatedTransformer):
             `MyClass(**params)` or `MyClass(**params[i])` creates a valid test instance.
             `create_test_instance` uses the first (or only) dictionary in `params`
         """
-        from aeon.transformations.boxcox import BoxCoxTransformer
-
         params1 = {"transformer": MockTransformer()}
-        # BoxCoxTransformer has fit
-        params2 = {"transformer": BoxCoxTransformer()}
+        # _BoxCoxTransformer has fit
+        params2 = {"transformer": _BoxCoxTransformer()}
 
         return [params1, params2]
 
@@ -1354,9 +1351,7 @@ class OptionalPassthrough(_DelegatedTransformer):
             `MyClass(**params)` or `MyClass(**params[i])` creates a valid test instance.
             `create_test_instance` uses the first (or only) dictionary in `params`
         """
-        from aeon.transformations.boxcox import BoxCoxTransformer
-
-        return {"transformer": BoxCoxTransformer(), "passthrough": False}
+        return {"transformer": _BoxCoxTransformer(), "passthrough": False}
 
 
 class ColumnwiseTransformer(BaseTransformer):
diff --git a/aeon/transformations/exponent.py b/aeon/transformations/exponent.py
index 33220558..d81f5f84 100644
--- a/aeon/transformations/exponent.py
+++ b/aeon/transformations/exponent.py
@@ -42,17 +42,6 @@ class ExponentTransformer(BaseTransformer):
         User supplied offset value.
         Scalar or 1D iterable with as many values as X columns in transform.
 
-    See Also
-    --------
-    BoxCoxTransformer :
-        Applies Box-Cox power transformation. Can help normalize data and
-        compress variance of the series.
-    LogTransformer :
-        Transformer input data using natural log. Can help normalize data and
-        compress variance of the series.
-    aeon.transformations.exponent.SqrtTransformer :
-        Transform input data by taking its square root. Can help compress
-        variance of input series.
 
     Notes
     -----
diff --git a/aeon/transformations/func_transform.py b/aeon/transformations/func_transform.py
index 75f0af86..8bf2e00d 100644
--- a/aeon/transformations/func_transform.py
+++ b/aeon/transformations/func_transform.py
@@ -50,17 +50,6 @@ class FunctionTransformer(BaseTransformer):
         if X passed to transform/inverse_transform is not on the list,
             it will be converted to the first list element before passed to funcs
 
-    See Also
-    --------
-    aeon.transformations.boxcox.LogTransformer :
-        Transformer input data using natural log. Can help normalize data and
-        compress variance of the series.
-    aeon.transformations.exponent.ExponentTransformer :
-        Transform input data by raising it to an exponent. Can help compress
-        variance of series if a fractional exponent is supplied.
-    aeon.transformations.exponent.SqrtTransformer :
-        Transform input data by taking its square root. Can help compress
-        variance of input series.
 
     Examples
     --------
diff --git a/aeon/transformations/kalman_filter.py b/aeon/transformations/kalman_filter.py
deleted file mode 100644
index c53a8b2f..00000000
--- a/aeon/transformations/kalman_filter.py
+++ /dev/null
@@ -1,745 +0,0 @@
-"""Kalman Filter Transformers.
-
-Series based transformers, based on Kalman Filter algorithm. Contains Base class
-and a transformer which is an adapter for the external package
-FilterPy.
-"""
-
-__maintainer__ = []
-__all__ = [
-    "BaseKalmanFilter",
-    "KalmanFilterTransformer",
-]
-
-from warnings import warn
-
-import numpy as np
-from deprecated.sphinx import deprecated
-
-from aeon.transformations.base import BaseTransformer
-
-
-def _get_t_matrix(time_t, matrices, shape, time_steps):
-    """Extract matrix to be used at iteration `time_t` of the Kalman filter iterations.
-
-    Parameters
-    ----------
-    time_t : int
-        The required time step.
-    matrices : np.ndarray
-    shape : tuple
-        The shape of a single matrix.
-    time_steps : int
-        Number of iterations.
-
-    Returns
-    -------
-        matrix : np.ndarray
-            matrix to be used at iteration `time_t`
-    """
-    matrices = np.asarray(matrices)
-    if matrices.shape == shape:
-        return matrices
-    if matrices.shape == (time_steps, *shape):
-        return matrices[time_t]
-    raise ValueError(
-        f"Shape of `matrices` {matrices.shape}, does not match single matrix"
-        f"`shape` {shape}, nor shape of list of matrices {(time_steps, *shape)}."
-    )
-
-
-def _validate_param_shape(param_name, matrix_shape, actual_shape, time_steps=None):
-    """Validate shape of matrix parameter.
-
-    Assert `actual_shape` equals to:
-        -   'shape' of a single matrix or
-        -   'shape' of time_steps matrices.
-    If neither, raise an informative `ValueError` that includes the parameter's name.
-
-    Parameters
-    ----------
-    param_name : str
-        The name of the matrix-parameter.
-    matrix_shape : tuple
-        The supposed shape of a single matrix.
-    actual_shape : tuple
-        The actual shape of matrix-parameter.
-    time_steps : int
-        actual_shape[0] if matrix-parameter is dynamic (matrix per time-step).
-
-    Raises
-    ------
-        ValueError
-            error with an informative message that includes parameter's name,
-            and the shape that parameter should have.
-    """
-    if time_steps is None:
-        if actual_shape != matrix_shape:
-            raise ValueError(
-                f"Shape of parameter `{param_name}` is: {actual_shape}, "
-                f"but should be: {matrix_shape}."
-            )
-    else:
-        matrices_shape = (time_steps, *matrix_shape)
-        if actual_shape not in [matrix_shape, matrices_shape]:
-            raise ValueError(
-                f"Shape of parameter `{param_name}` is: {actual_shape}, but should be: "
-                f"{matrix_shape} or {matrices_shape}."
-            )
-
-
-def _init_matrix(matrices, transform_func, default_val):
-    """Initialize default value if matrices.
-
-    If `matrices` is None, or transform input matrix to np.ndarray.
-
-    Parameters
-    ----------
-    matrices : np.ndarray
-    transform_func : transformation function from array-like to ndarray
-    default_val : np.ndarray
-
-    Returns
-    -------
-        transformed_matrices : np.ndarray
-            matrices as np.ndarray
-    """
-    return default_val if matrices is None else transform_func(matrices)
-
-
-# TODO: remove in v0.10.0
-@deprecated(
-    version="0.9.0",
-    reason="BaseKalmanFilter will be removed in version 0.10.",
-    category=FutureWarning,
-)
-class BaseKalmanFilter:
-    """Kalman Filter is used for denoising data, or inferring the hidden state of data.
-
-    Note - this class is a base class and should not be used directly.
-
-    The Kalman filter is an unsupervised algorithm consisting of
-    several mathematical equations which are used to create
-    an estimate of the state of a process.
-    The algorithm does this efficiently and recursively in a
-    way where the mean squared error is minimal.
-    The Kalman Filter has the ability to support estimations
-    of past, present and future states.
-    The strength of the Kalman Filter is in its ability to
-    infer the state of a system even when the exact nature of the
-    system is not known.
-    When given time series data, the Kalman filter creates a denoising effect
-    by removing noise from the data, and recovering the true
-    state of the underlying object we are tracking within the
-    data.
-    The Kalman Filter computations are based on five equations.
-
-    Two prediction equations:
-
-    -   State Extrapolation Equation - prediction or estimation of the future state,
-        based on the known present estimation.
-    -	Covariance Extrapolation Equation - the measure of uncertainty in our prediction.
-
-    Two update equations:
-
-    -   State Update Equation - estimation of the current state,
-        based on the known past estimation and present measurement.
-    -	Covariance Update Equation - the measure of uncertainty in our estimation.
-
-    Kalman Gain Equation – this is a required argument for the update equations.
-    It acts as a weighting parameter for the past estimations and the given measurement.
-    It defines the weight of the past estimation and
-    the weight of the measurement in estimating the current state.
-
-    Parameters
-    ----------
-    state_dim : int
-        System state feature dimension
-    state_transition : np.ndarray, default=None
-        of shape (state_dim, state_dim) or (time_steps, state_dim, state_dim).
-        State transition matrix, also referred to as F, is a matrix
-        which describes the way the underlying series moves
-        through successive time periods.
-    process_noise : np.ndarray, default=None
-        of shape (state_dim, state_dim) or (time_steps, state_dim, state_dim).
-        Process noise matrix, also referred to as Q,
-        the uncertainty of the dynamic model.
-    measurement_noise : np.ndarray, default=None
-        of shape (measurement_dim, measurement_dim) or
-        (time_steps, measurement_dim, measurement_dim).
-        Measurement noise matrix, also referred to as R,
-        represents the uncertainty of the measurements.
-    measurement_function : np.ndarray, default=None
-        of shape (measurement_dim, state_dim) or
-        (time_steps, measurement_dim, state_dim).
-        Measurement equation matrix, also referred to as H, adjusts
-        dimensions of measurements to match dimensions of state.
-    initial_state : np.ndarray, default=None
-        of shape (state_dim,).
-        Initial estimated system state, also referred to as x0.
-    initial_state_covariance : np.ndarray, default=None
-        of shape (state_dim, state_dim).
-        Initial estimated system state covariance, also referred to as P0.
-
-    References
-    ----------
-    .. [1] Greg Welch and Gary Bishop, "An Introduction to the Kalman Filter", 2006
-           https://www.cs.unc.edu/~welch/media/pdf/kalman_intro.pdf
-    .. [2] R.H.Shumway and D.S.Stoffer "An Approach to time
-           Series Smoothing and Forecasting Using the EM Algorithm", 1982
-           https://www.stat.pitt.edu/stoffer/dss_files/em.pdf
-    """
-
-    def __init__(
-        self,
-        state_dim,
-        state_transition=None,
-        process_noise=None,
-        measurement_noise=None,
-        measurement_function=None,
-        initial_state=None,
-        initial_state_covariance=None,
-    ):
-        self.state_dim = state_dim
-        # F/A
-        self.state_transition = state_transition
-        # Q
-        self.process_noise = process_noise
-        # R
-        self.measurement_noise = measurement_noise
-        # H/C
-        self.measurement_function = measurement_function
-        # X0
-        self.initial_state = initial_state
-        # P0
-        self.initial_state_covariance = initial_state_covariance
-
-        super().__init__()
-
-    def _get_shapes(self, state_dim, measurement_dim):
-        """Return dictionary with default shape of each matrix parameter.
-
-        Parameters
-        ----------
-        state_dim : int
-            Dimension of `state`.
-        measurement_dim : int
-            Dimension of measurements.
-
-        Returns
-        -------
-            shapes : dict
-                Dictionary with default shape of each matrix parameter
-        """
-        return {
-            "F": (state_dim, state_dim),
-            "Q": (state_dim, state_dim),
-            "R": (measurement_dim, measurement_dim),
-            "H": (measurement_dim, state_dim),
-            "X0": (state_dim,),
-            "P0": (state_dim, state_dim),
-        }
-
-    def _get_init_values(self, measurement_dim, state_dim):
-        """Initialize matrix parameters to default values and returns them.
-
-        Parameters
-        ----------
-        measurement_dim : int
-        state_dim : int
-
-        Returns
-        -------
-            Six matrix parameters F,Q,R,H,X0,P0 as np.ndarray
-        """
-        shapes = self._get_shapes(state_dim=state_dim, measurement_dim=measurement_dim)
-        F = _init_matrix(
-            matrices=self.state_transition,
-            transform_func=np.atleast_2d,
-            default_val=np.eye(*shapes["F"]),
-        )
-        Q = _init_matrix(
-            matrices=self.process_noise,
-            transform_func=np.atleast_2d,
-            default_val=np.eye(*shapes["Q"]),
-        )
-        R = _init_matrix(
-            matrices=self.measurement_noise,
-            transform_func=np.atleast_2d,
-            default_val=np.eye(*shapes["R"]),
-        )
-        H = _init_matrix(
-            matrices=self.measurement_function,
-            transform_func=np.atleast_2d,
-            default_val=np.eye(*shapes["H"]),
-        )
-        X0 = _init_matrix(
-            matrices=self.initial_state,
-            transform_func=np.atleast_1d,
-            default_val=np.zeros(*shapes["X0"]),
-        )
-        P0 = _init_matrix(
-            matrices=self.initial_state_covariance,
-            transform_func=np.atleast_2d,
-            default_val=np.eye(*shapes["P0"]),
-        )
-
-        return F, Q, R, H, X0, P0
-
-    def _set_attribute(
-        self, param_name, attr_name, value, matrix_shape, time_steps=None
-    ):
-        """Validate the shape of parameter and set as attribute if no error.
-
-        Parameters
-        ----------
-        param_name : str
-            The name of matrix-parameter.
-        attr_name : str
-            The name of corresponding attribute.
-        value : np.ndarray
-            The value of corresponding attribute.
-        matrix_shape : tuple
-            The supposed shape of a single matrix.
-        time_steps : int, default=None
-        """
-        _validate_param_shape(
-            param_name=param_name,
-            matrix_shape=matrix_shape,
-            actual_shape=value.shape,
-            time_steps=time_steps,
-        )
-        setattr(self, attr_name, value)
-
-
-# TODO: remove in v0.10.0
-@deprecated(
-    version="0.9.0",
-    reason="KalmanFilterTransformer will be removed in version 0.10.",
-    category=FutureWarning,
-)
-class KalmanFilterTransformer(BaseKalmanFilter, BaseTransformer):
-    """Kalman Filter Transformer.
-
-    Kalman Filter is used for denoising data or inferring the hidden
-    state of given data.
-
-    The Kalman Filter is an unsupervised algorithm, consisting of
-    several mathematical equations which are used to create
-    an estimate of the state of a process.
-
-    This class is the adapter for the `FilterPy` package into `aeon`.
-    `KalmanFilterTransformer` implements hidden inferred states and
-    denoising, depending on the boolean input parameter `denoising`.
-    In addition, `KalmanFilterTransformer` provides parameter
-    optimization via Expectation-Maximization (EM) algorithm.
-
-    Parameters
-    ----------
-    state_dim : int
-        System state feature dimension.
-    state_transition : np.ndarray, default=None
-        of shape (state_dim, state_dim) or (time_steps, state_dim, state_dim).
-        State transition matrix, also referred to as `F`, is a matrix
-        which describes the way the underlying series moves
-        through successive time periods.
-    process_noise : np.ndarray, default=None
-        of shape (state_dim, state_dim) or (time_steps, state_dim, state_dim).
-        Process noise matrix, also referred to as `Q`,
-        the uncertainty of the dynamic model.
-    measurement_noise : np.ndarray, default=None
-        of shape (measurement_dim, measurement_dim) or
-        (time_steps, measurement_dim, measurement_dim).
-        Measurement noise matrix, also referred to as `R`,
-        represents the uncertainty of the measurements.
-    measurement_function : np.ndarray, default=None
-        of shape (measurement_dim, state_dim) or
-        (time_steps, measurement_dim, state_dim).
-        Measurement equation matrix, also referred to as `H`, adjusts
-        dimensions of measurements to match dimensions of state.
-    initial_state : np.ndarray, default=None
-        of shape (state_dim,).
-        Initial estimated system state, also referred to as `X0`.
-    initial_state_covariance : np.ndarray, default=None
-        of shape (state_dim, state_dim).
-        Initial estimated system state covariance, also referred to as `P0`.
-    control_transition : np.ndarray, default=None
-        of shape (state_dim, control_variable_dim) or
-        (time_steps, state_dim, control_variable_dim).
-        Control transition matrix, also referred to as `G`.
-        `control_variable_dim` is the dimension of `control variable`,
-        also referred to as `u`.
-        `control variable` is an optional parameter for `fit` and `transform` functions.
-    denoising : bool, default=False
-        This parameter affects `transform`. If False, then `transform` will be inferring
-        hidden state. If True, uses `FilterPy` `rts_smoother` for denoising.
-    estimate_matrices : str or list of str, default=None
-        Subset of [`state_transition`, `measurement_function`,
-        `process_noise`, `measurement_noise`, `initial_state`,
-        `initial_state_covariance`]
-        or - `all`. If `estimate_matrices` is an iterable of strings,
-        only matrices in `estimate_matrices` will be estimated using EM algorithm.
-        If `estimate_matrices` is `all`,
-        then all matrices will be estimated using EM algorithm.
-
-        Note -
-            - parameters estimated by EM algorithm assumed to be constant.
-            - `control_transition` matrix cannot be estimated.
-
-    Notes
-    -----
-    `FilterPy` KalmanFilter documentation :
-        https://filterpy.readthedocs.io/en/latest/kalman/KalmanFilter.html
-
-    References
-    ----------
-    .. [1] Greg Welch and Gary Bishop, "An Introduction to the Kalman Filter", 2006
-           https://www.cs.unc.edu/~welch/media/pdf/kalman_intro.pdf
-    .. [2] R.H.Shumway and D.S.Stoffer "An Approach to time
-           Series Smoothing and Forecasting Using the EM Algorithm", 1982
-           https://www.stat.pitt.edu/stoffer/dss_files/em.pdf
-
-    Examples
-    --------
-        Basic example:
-    >>> import numpy as np  # doctest: +SKIP
-    >>> import aeon.transformations.kalman_filter as kf
-    >>> time_steps, state_dim, measurement_dim = 10, 2, 3
-    >>>
-    >>> X = np.random.rand(time_steps, measurement_dim) * 10
-    >>> transformer = kf.KalmanFilterTransformer(state_dim=state_dim) # doctest: +SKIP
-    >>> Xt = transformer.fit_transform(X=X)  # doctest: +SKIP
-
-        Example of - denoising, matrix estimation, missing values and transform with y:
-    >>> import numpy as np  # doctest: +SKIP
-    >>> import aeon.transformations.kalman_filter as kf
-    >>> time_steps, state_dim, measurement_dim = 10, 3, 3
-    >>> control_variable_dim = 2
-    >>>
-    >>> X = np.random.rand(time_steps, measurement_dim)
-    >>> # missing value
-    >>> X[0][0] = np.nan
-    >>>
-    >>> # y
-    >>> control_variable = np.random.rand(time_steps, control_variable_dim)
-    >>>
-    >>> # If matrices estimation is required, elements of `estimate_matrices`
-    >>> # are assumed to be constants.
-    >>> transformer = kf.KalmanFilterTransformer(  # doctest: +SKIP
-    ...     state_dim=state_dim,
-    ...     measurement_noise=np.eye(measurement_dim),
-    ...     denoising=True,
-    ...     )
-    >>> Xt = transformer.fit_transform(X=X, y=control_variable)  # doctest: +SKIP
-
-        Example of - dynamic inputs (matrix per time-step), missing values:
-    >>> import numpy as np  # doctest: +SKIP
-    >>> import aeon.transformations.kalman_filter as kf
-    >>> time_steps, state_dim, measurement_dim = 10, 4, 4
-    >>> control_variable_dim = 4
-    >>>
-    >>> X = np.random.rand(time_steps, measurement_dim)
-    >>> # missing values
-    >>> X[0] = [np.NaN for i in range(measurement_dim)]
-    >>>
-    >>> # y
-    >>> control_variable = np.random.rand(control_variable_dim)
-    >>>
-    >>> # Dynamic input -
-    >>> # `state_transition` provide different matrix for each time step.
-    >>> transformer = kf.KalmanFilterTransformer(  # doctest: +SKIP
-    ...     state_dim=state_dim,
-    ...     state_transition=np.random.rand(time_steps, state_dim, state_dim),
-    ...     )
-    >>> Xt = transformer.fit_transform(X=X, y=control_variable)  # doctest: +SKIP
-    """
-
-    _tags = {
-        "transform_labels": "Series",
-        "X_inner_type": "np.ndarray",
-        "y_inner_type": "np.ndarray",
-        "fit_is_empty": False,
-        "capability:unequal_length": False,
-        "capability:missing_values": True,  # can estimator handle missing data?
-        "capability:missing_values:removes": False,
-        "instancewise": True,  # is this an instance-wise transform?
-        "python_dependencies": ["filterpy", "numpy<1.24.0"],
-    }
-
-    def __init__(
-        self,
-        state_dim,
-        state_transition=None,
-        control_transition=None,
-        process_noise=None,
-        measurement_noise=None,
-        measurement_function=None,
-        initial_state=None,
-        initial_state_covariance=None,
-        estimate_matrices=None,
-        denoising=False,
-    ):
-        super().__init__(
-            state_dim=state_dim,
-            state_transition=state_transition,
-            process_noise=process_noise,
-            measurement_noise=measurement_noise,
-            measurement_function=measurement_function,
-            initial_state=initial_state,
-            initial_state_covariance=initial_state_covariance,
-        )
-        # G/B
-        self.control_transition = control_transition
-        self.estimate_matrices = estimate_matrices
-        self.denoising = denoising
-
-    def _fit(self, X, y=None):
-        """Fit transformer to X and y.
-
-        This method prepares the transformer.
-        The matrix initializations or estimations
-        (if requested by user) are calculated here.
-
-        Parameters
-        ----------
-        X : np.ndarray
-            of shape (time_steps, measurement_dim).
-            Data (measurements) to be transformed.
-            Missing values must be represented as np.NaN or np.nan.
-        y : ignored argument for interface compatibility
-
-        Returns
-        -------
-            self: reference to self
-        """
-        measurement_dim = X.shape[1]
-        time_steps = X.shape[0]
-        shapes = self._get_shapes(
-            state_dim=self.state_dim, measurement_dim=measurement_dim
-        )
-
-        if self.estimate_matrices is None:
-            (F_, Q_, R_, H_, X0_, P0_) = self._get_init_values(
-                measurement_dim, self.state_dim
-            )
-
-        self._set_attribute(
-            param_name="state_transition",
-            attr_name="F_",
-            value=F_,
-            matrix_shape=shapes["F"],
-            time_steps=time_steps,
-        )
-        self._set_attribute(
-            param_name="process_noise",
-            attr_name="Q_",
-            value=Q_,
-            matrix_shape=shapes["Q"],
-            time_steps=time_steps,
-        )
-        self._set_attribute(
-            param_name="measurement_noise",
-            attr_name="R_",
-            value=R_,
-            matrix_shape=shapes["R"],
-            time_steps=time_steps,
-        )
-        self._set_attribute(
-            param_name="measurement_function",
-            attr_name="H_",
-            value=H_,
-            matrix_shape=shapes["H"],
-            time_steps=time_steps,
-        )
-        self._set_attribute(
-            param_name="initial_state",
-            attr_name="X0_",
-            value=X0_,
-            matrix_shape=shapes["X0"],
-        )
-        self._set_attribute(
-            param_name="initial_state_covariance",
-            attr_name="P0_",
-            value=P0_,
-            matrix_shape=shapes["P0"],
-        )
-
-        return self
-
-    def _transform(self, X, y=None):
-        """Transform X and return a transformed version.
-
-        This method performs the transformation of the input data
-        according to the constructor input parameter `denoising`.
-        If `denoising` is True - then denoise data using
-        `FilterPy`'s `rts_smoother` function.
-        Else, infer hidden state using `FilterPy`'s `predict` and `update` functions.
-
-        Parameters
-        ----------
-        X : np.ndarray
-            of shape (time_steps, measurement_dim).
-            Data (measurements) to be transformed.
-            Missing values must be represented as np.NaN or np.nan.
-        y : np.ndarray, default=None
-            of shape (control_variable_dim,) or (time_steps, control_variable_dim).
-            `control variable`, also referred to as `u`.
-            if 2D, must be same length as X.
-
-        Returns
-        -------
-            X_transformed : np.ndarray
-                transformed version of X
-        """
-        import filterpy.kalman.kalman_filter as filterpy_kf
-
-        time_steps = X.shape[0]
-        measurement_dim = X.shape[1]
-
-        if y is None:
-            if self.control_transition is None:
-                y_dim = 1
-            else:
-                y_dim = np.atleast_2d(self.control_transition).shape[-1]
-                warn(
-                    "Class parameter `control_transition` was initiated with user data "
-                    "but received no data through `transform` argument, `y`. "
-                    "Therefore, omitting `control_transition` "
-                    "when calculating the result. ",
-                    stacklevel=2,
-                )
-            y = np.zeros(y_dim)
-
-        shapes = self._get_shapes(
-            state_dim=self.state_dim, measurement_dim=measurement_dim, u_dim=y.shape[-1]
-        )
-        G = _init_matrix(
-            matrices=self.control_transition,
-            transform_func=np.atleast_2d,
-            default_val=np.eye(*shapes["G"]),
-        )
-        _validate_param_shape(
-            param_name="control_transition",
-            matrix_shape=shapes["G"],
-            actual_shape=G.shape,
-            time_steps=time_steps,
-        )
-
-        x_priori = np.zeros((time_steps, *shapes["X0"]))
-        p_priori = np.zeros((time_steps, *shapes["P0"]))
-
-        x_posteriori = np.zeros((time_steps, *shapes["X0"]))
-        p_posteriori = np.zeros((time_steps, *shapes["P0"]))
-
-        x = self.X0_
-        p = self.P0_
-
-        # kalman filter iterations
-        for t in range(time_steps):
-            (zt, Ft, Gt, Qt, Rt, Ht, ut) = self._get_iter_t_matrices(
-                X=X, G=G, u=y, t=t, time_steps=time_steps, shapes=shapes
-            )
-
-            x, p = filterpy_kf.predict(x, p, u=ut, B=Gt, F=Ft, Q=Qt)
-            x_priori[t, :] = x
-            p_priori[t, :, :] = p
-
-            x, p = filterpy_kf.update(x, p, zt, R=Rt, H=Ht)
-            x_posteriori[t, :] = x
-            p_posteriori[t, :, :] = p
-
-        if self.denoising:
-            Fs = [self.F_] * time_steps if self.F_.ndim == 2 else self.F_
-            Qs = [self.Q_] * time_steps if self.Q_.ndim == 2 else self.Q_
-            return filterpy_kf.rts_smoother(
-                Xs=x_posteriori, Ps=p_posteriori, Fs=Fs, Qs=Qs
-            )[0]
-        return x_posteriori
-
-    @classmethod
-    def get_test_params(cls, parameter_set="default"):
-        """Return testing parameter settings for the estimator.
-
-        Parameters
-        ----------
-        parameter_set : str, default="default"
-            Name of the set of test parameters to return, for use in tests. If no
-            special parameters are defined for a value, will return `"default"` set.
-            There are currently no reserved values for transformers.
-
-        Returns
-        -------
-        params : dict or list of dict, default = {}
-            Parameters to create testing instances of the class
-            Each dict are parameters to construct an "interesting" test instance, i.e.,
-            `MyClass(**params)` or `MyClass(**params[i])` creates a valid test instance.
-            `create_test_instance` uses the first (or only) dictionary in `params`
-        """
-        return {"state_dim": 2}
-
-    def _get_iter_t_matrices(self, X, G, u, t, time_steps, shapes):
-        """Extract data to be used at time step 't' of the Kalman filter iterations.
-
-        Parameters
-        ----------
-        X : np.ndarray
-            of shape (time_steps, measurement_dim).
-            Data (measurements).
-        G : np.ndarray
-            of shape (state_dim, control_variable_dim) or
-            (time_steps, state_dim, control_variable_dim).
-            control_transition matrix
-        u : np.ndarray
-            of shape (control_variable_dim,) or (time_steps, control_variable_dim).
-            u is the `control variable`. If `u` not given in _transform default
-            value is [0].
-        t : int
-            time step
-
-        Returns
-        -------
-            Seven matrices to be used at time step t
-        """
-        zt = None if any(np.isnan(X[t])) else X[t]
-        Ft = _get_t_matrix(
-            time_t=t, matrices=self.F_, shape=shapes["F"], time_steps=time_steps
-        )
-        Gt = _get_t_matrix(
-            time_t=t, matrices=G, shape=shapes["G"], time_steps=time_steps
-        )
-        Qt = _get_t_matrix(
-            time_t=t, matrices=self.Q_, shape=shapes["Q"], time_steps=time_steps
-        )
-        Rt = _get_t_matrix(
-            time_t=t, matrices=self.R_, shape=shapes["R"], time_steps=time_steps
-        )
-        Ht = _get_t_matrix(
-            time_t=t, matrices=self.H_, shape=shapes["H"], time_steps=time_steps
-        )
-        ut = _get_t_matrix(
-            time_t=t, matrices=u, shape=shapes["u"], time_steps=time_steps
-        )
-
-        return zt, Ft, Gt, Qt, Rt, Ht, ut
-
-    def _get_shapes(self, state_dim, measurement_dim, u_dim=1):
-        """Return dictionary with default shape of each matrix parameter.
-
-        Parameters
-        ----------
-        state_dim : int
-            Dimension of `state`.
-        measurement_dim : int
-            Dimension of measurements.
-        u_dim : int
-            Dimension of control variable u (y).
-
-        Returns
-        -------
-            shapes : dict
-                Dictionary with default shape of each matrix parameter
-        """
-        shapes = super()._get_shapes(state_dim, measurement_dim)
-        shapes["u"] = (u_dim,)
-        shapes["G"] = (state_dim, u_dim)
-        return shapes
diff --git a/aeon/transformations/scaledlogit.py b/aeon/transformations/scaledlogit.py
index 80b8ef76..4ea8af2b 100644
--- a/aeon/transformations/scaledlogit.py
+++ b/aeon/transformations/scaledlogit.py
@@ -36,10 +36,10 @@ class ScaledLogitTransformer(BaseTransformer):
 
     See Also
     --------
-    aeon.transformations.boxcox.LogTransformer :
+    aeon.transformations.boxcox._LogTransformer :
         Transformer input data using natural log. Can help normalize data and
         compress variance of the series.
-    aeon.transformations.boxcox.BoxCoxTransformer :
+    aeon.transformations.boxcox._BoxCoxTransformer :
         Applies Box-Cox power transformation. Can help normalize data and
         compress variance of the series.
     aeon.transformations.exponent.ExponentTransformer :
diff --git a/aeon/transformations/series/_boxcox.py b/aeon/transformations/series/_boxcox.py
index 71575dc2..41edd97a 100644
--- a/aeon/transformations/series/_boxcox.py
+++ b/aeon/transformations/series/_boxcox.py
@@ -46,7 +46,7 @@ class BoxCoxTransformer(BaseSeriesTransformer):
     make data more normally distributed and stabilize its variance based
     on the hyperparameter lambda. [1]_
 
-    The BoxCoxTransformer solves for the lambda parameter used in the Box-Cox
+    The _BoxCoxTransformer solves for the lambda parameter used in the Box-Cox
     transformation given `method`, the optimization approach, and input
     data provided to `fit`. The use of Guerrero's method for solving for lambda
     requires the seasonal periodicity, `sp` be provided. [2]_
@@ -79,7 +79,7 @@ class BoxCoxTransformer(BaseSeriesTransformer):
 
     See Also
     --------
-    LogTransformer :
+    _LogTransformer :
         Transformer input data using natural log. Can help normalize data and
         compress variance of the series.
     aeon.transformations.exponent.ExponentTransformer :
@@ -107,7 +107,7 @@ class BoxCoxTransformer(BaseSeriesTransformer):
 
     Examples
     --------
-    >>> from aeon.transformations.boxcox import BoxCoxTransformer
+    >>> from aeon.transformations.series._boxcox import BoxCoxTransformer
     >>> from aeon.datasets import load_airline
     >>> y = load_airline()
     >>> transformer = BoxCoxTransformer()
@@ -212,7 +212,7 @@ class LogTransformer(BaseSeriesTransformer):
 
     See Also
     --------
-    BoxCoxTransformer :
+    _BoxCoxTransformer :
         Applies Box-Cox power transformation. Can help normalize data and
         compress variance of the series.
     aeon.transformations.exponent.ExponentTransformer :
@@ -228,7 +228,7 @@ class LogTransformer(BaseSeriesTransformer):
 
     Examples
     --------
-    >>> from aeon.transformations.boxcox import LogTransformer
+    >>> from aeon.transformations.series._boxcox import LogTransformer
     >>> from aeon.datasets import load_airline
     >>> y = load_airline()
     >>> transformer = LogTransformer()
diff --git a/aeon/transformations/series/_scaled_logit.py b/aeon/transformations/series/_scaled_logit.py
index ecc93389..1cb97ac3 100644
--- a/aeon/transformations/series/_scaled_logit.py
+++ b/aeon/transformations/series/_scaled_logit.py
@@ -34,20 +34,6 @@ class ScaledLogitSeriesTransformer(BaseSeriesTransformer):
     upper_bound : float, optional, default=None
         upper bound of inverse transform function
 
-    See Also
-    --------
-    aeon.transformations.boxcox.LogTransformer :
-        Transformer input data using natural log. Can help normalize data and
-        compress variance of the series.
-    aeon.transformations.boxcox.BoxCoxTransformer :
-        Applies Box-Cox power transformation. Can help normalize data and
-        compress variance of the series.
-    aeon.transformations.exponent.ExponentTransformer :
-        Transform input data by raising it to an exponent. Can help compress
-        variance of series if a fractional exponent is supplied.
-    aeon.transformations.exponent.SqrtTransformer :
-        Transform input data by taking its square root. Can help compress
-        variance of input series.
 
     Notes
     -----
diff --git a/aeon/transformations/time_since.py b/aeon/transformations/time_since.py
deleted file mode 100644
index 1da801d5..00000000
--- a/aeon/transformations/time_since.py
+++ /dev/null
@@ -1,346 +0,0 @@
-"""A transformer to compute the time elapsed since a reference time."""
-
-from __future__ import annotations
-
-__maintainer__ = []
-
-import datetime
-import warnings
-from string import digits
-
-import numpy as np
-import pandas as pd
-from deprecated.sphinx import deprecated
-from pandas.api.types import is_any_real_numeric_dtype
-from pandas.tseries.frequencies import get_period_alias
-
-from aeon.transformations.base import BaseTransformer
-
-
-# TODO: remove in v0.10.0
-@deprecated(
-    version="0.9.0",
-    reason="TimeSince will be removed in version 0.10 and may be replaced with a "
-    "BaseSeriesTransformer version in the transformations.series module.",
-    category=FutureWarning,
-)
-class TimeSince(BaseTransformer):
-    """Get Element-wise time elapsed between the timeindex and a reference start time.
-
-    Creates a column(s) which represents: `t` - `start`, where `start` is
-    a reference time and `t` is the time index. The type of `start` must be
-    compatible with the index of `X` used in `.fit()` and `.transform()`.
-
-    The output can be converted to an integer representing the number of periods
-    elapsed since the start time by setting `to_numeric=True`. The period is
-    determined by the frequency of the index. For example, if the `freq` of
-    the index is "MS" or "M" then the output is the integer number of months
-    between `t` and `start`.
-
-    Parameters
-    ----------
-    start : a list of start times, optional, default=None (use earliest time in index)
-        a "start time" can be one of the following types:
-
-        * int: Start time to compute the time elapsed, use when index is integer.
-        * time-like: `Period` or `datetime`
-            Start time to compute the time elapsed.
-        * str: String is converted to datetime or period, depending on the index type, \
-            to give the start time.
-
-    to_numeric : string, default=True
-        Return the integer number of periods elapsed since `start`; the period
-        is defined by the frequency of the data. Converts datetime types to
-        pd.Period before calculating time differences.
-    freq : 'str', optional, default=None
-        Only used when X has a pd.DatetimeIndex without a specified frequency.
-        Specifies the frequency of the index of your data. The string should
-        match a pandas offset alias:
-        https://pandas.pydata.org/pandas-docs/stable/user_guide/timeseries.html#offset-aliases
-    keep_original_columns :  boolean, optional, default=False
-        Keep original columns in X passed to `.transform()`.
-    positive_only :  boolean, optional, default=False
-        Clips negative values to zero when `to_numeric` is True.
-
-    Examples
-    --------
-    >>> from aeon.datasets import load_airline
-    >>> from aeon.transformations.time_since import TimeSince
-    >>> X = load_airline()
-
-        Create a single column with time elapsed since start date of time series.
-        The output is in units of integer number of months, same as the index `freq`.
-    >>> transformer = TimeSince()
-    >>> Xt = transformer.fit_transform(X)
-
-        Create multiple columns with different start times. The output is in units
-        of integer number of months, same as the index `freq`.
-    >>> transformer = TimeSince(["2000-01", "2000-02"])
-    >>> Xt = transformer.fit_transform(X)
-    """
-
-    _tags = {
-        # what is the abstract type of X: Series, or Panel
-        "input_data_type": "Series",
-        # what abstract type is returned: Primitives, Series, Panel
-        "output_data_type": "Series",
-        "instancewise": True,  # is this an instance-wise transform?
-        "transform_labels": "None",
-        "X_inner_type": ["pd.DataFrame", "pd-multiindex", "pd_multiindex_hier"],
-        "y_inner_type": "None",
-        "univariate-only": False,
-        "requires_y": False,
-        "remember_data": False,
-        "fit_is_empty": False,  # is fit empty and can be skipped?
-        "X-y-must-have-same-index": False,
-        "enforce_index_type": [pd.PeriodIndex, pd.DatetimeIndex],
-        "transform-returns-same-time-index": True,
-        "capability:inverse_transform": False,  # can the transformer inverse transform?
-        "skip-inverse-transform": True,  # is inverse-transform skipped when called?
-        "capability:unequal_length": True,
-        "capability:unequal_length:removes": False,
-        "capability:missing_values": True,  # can estimator handle missing data?
-        "capability:missing_values:removes": False,
-    }
-
-    def __init__(
-        self,
-        start: list[str | datetime.datetime | pd.Period | None] | None = None,
-        *,
-        to_numeric: bool | None = True,
-        freq: str | None = None,
-        keep_original_columns: bool | None = False,
-        positive_only: bool | None = False,
-    ):
-        self.start = start
-        self.to_numeric = to_numeric
-        self.freq = freq
-        self.keep_original_columns = keep_original_columns
-        self.positive_only = positive_only
-        super().__init__()
-
-    def _fit(self, X, y=None):
-        """Fit transformer to X and y.
-
-        private _fit containing the core logic, called from fit
-
-        Parameters
-        ----------
-        X: data structure of type X_inner_type
-            if X_inner_type is list, _fit must support all types in it
-            Data to fit transform to
-        y : data structure of type y_inner_type, default=None
-            Additional data, e.g., labels for transformation
-
-        Returns
-        -------
-        self: reference to self
-        """
-        time_index = _get_time_index(X)
-
-        if is_any_real_numeric_dtype(time_index):
-            if self.freq:
-                warnings.warn(
-                    "Index is integer type. `freq` will be ignored.", stacklevel=2
-                )
-            self.freq_ = None
-        elif isinstance(time_index, (pd.DatetimeIndex, pd.PeriodIndex)):
-            # Chooses first non None value
-            self.freq_ = time_index.freqstr or self.freq or pd.infer_freq(time_index)
-            if self.freq_ is None:
-                raise ValueError("X has no known frequency and none is supplied")
-            if (
-                (self.freq_ == time_index.freqstr)
-                and (self.freq_ != self.freq)
-                and (self.freq)
-            ):
-                warnings.warn(
-                    f"Using frequency from index: {time_index.freq}, which "
-                    f"does not match the frequency given: {self.freq}.",
-                    stacklevel=2,
-                )
-        else:
-            raise ValueError("Index must be of type int, datetime, or period.")
-
-        self.start_ = []
-        if self.start is None:
-            self.start_.append(time_index.min())
-        else:
-            for start in self.start:
-                if start is None:
-                    self.start_.append(time_index.min())
-                elif isinstance(start, str):
-                    if isinstance(time_index, pd.PeriodIndex):
-                        self.start_.append(pd.Period(start))
-                    else:
-                        self.start_.append(pd.to_datetime(start))
-                else:
-                    self.start_.append(start)
-
-        # Check `start_` is compatible with index
-        for start_ in self.start_:
-            if isinstance(time_index, pd.DatetimeIndex) and not isinstance(
-                start_, datetime.datetime
-            ):
-                raise ValueError(
-                    f"start_={start_} incompatible with a "
-                    f"datetime index. Check that `start` is of type "
-                    f"datetime or a pd.Datetime parsable string."
-                )
-            elif isinstance(time_index, pd.PeriodIndex) and not isinstance(
-                start_, pd.Period
-            ):
-                raise ValueError(
-                    f"start_={start_} incompatible with a "
-                    f"Period index. Check that `start` is of type "
-                    f"pd.Period or a pd.Period parsable string."
-                )
-            elif is_any_real_numeric_dtype(time_index) and not isinstance(
-                start_, (int, np.integer)
-            ):
-                raise ValueError(
-                    f"start_={start_} incompatible with a numeric index."
-                    f"Check that `start` is an integer."
-                )
-
-        return self
-
-    def _transform(self, X, y=None):
-        """Transform X and return a transformed version.
-
-        private _transform containing core logic, called from transform
-
-        Parameters
-        ----------
-        X: data structure of type X_inner_type
-            if X_inner_type is list, _transform must support all types in it
-            Data to be transformed
-        y : data structure of type y_inner_type, default=None
-            Additional data, e.g., labels for transformation
-
-        Returns
-        -------
-        transformed version of X
-        """
-        time_index = _get_time_index(X)
-
-        Xt = pd.DataFrame(index=X.index)
-        for start_ in self.start_:
-            if self.to_numeric:
-                if isinstance(time_index, pd.DatetimeIndex):
-                    # To support calculating integer time differences when `freq`
-                    # is not compatible with timedelta type (e.g., "M", "MS", "Y")
-                    # X.index and `start` are first converted to pandas Period.
-
-                    # Infer the freq needed to convert to period. We use the
-                    # `get_period_alas` helper method from Pandas. This method
-                    # maps from a frequency that is compatible with a datetime
-                    # index to one that is compatible with a period index
-                    # (e.g., "MS" -> "M"). We must strip the freq str of any
-                    # integer multiplier (e.g., "15T" -> "T"). This is needed so that
-                    # `get_period_alias` returns the correct result.
-                    # If `get_period_alias` recieves a freq str with a multiplier
-                    # (e.g., "15T") it returns `None` which causes errors downstream.
-                    freq_ = _remove_digits_from_str(self.freq_)
-                    freq_period = get_period_alias(freq_)
-
-                    # Convert `start` and `time_index` to period.
-                    # Casting `start_` to PeriodIndex using pd.period_range
-                    # here so we can later cast it to an int using
-                    # `astype(int)` in _get_period_diff_as_int().
-                    start_period = pd.period_range(
-                        start=start_, periods=1, freq=freq_period
-                    )
-                    time_index_period = time_index.to_period(freq=freq_period)
-                    # Compute time differences.
-                    time_deltas = _get_period_diff_as_int(
-                        time_index_period, start_period
-                    )
-
-                elif isinstance(time_index, pd.PeriodIndex):
-                    if pd.__version__ < "1.5.0":
-                        # Earlier versions of pandas returned incorrect result
-                        # when taking a difference between Periods when the frequency
-                        # is a multiple of a unit (e.g. "15T"). Solution is to
-                        # cast to lowest frequency when taking difference (e.g., "T").
-                        freq_ = _remove_digits_from_str(self.freq_)
-
-                        # Change freq of `start` and `time_index`.
-                        # Casting `start_` to PeriodIndex using pd.period_range
-                        # here so we can later cast it to an int using
-                        # `astype(int)` in _get_period_diff_as_int().
-                        start_period = pd.period_range(
-                            start=start_.to_timestamp(), periods=1, freq=freq_
-                        )
-                        time_index = time_index.to_timestamp().to_period(freq_)
-                    else:
-                        # Casting `start_` to PeriodIndex using pd.period_range
-                        # here so we can later cast it to an int using
-                        # `astype(int)` in _get_period_diff_as_int().
-                        start_period = pd.period_range(
-                            start=start_, periods=1, freq=self.freq_
-                        )
-
-                    # Compute time differences.
-                    time_deltas = _get_period_diff_as_int(time_index, start_period)
-
-                elif is_any_real_numeric_dtype(time_index):
-                    time_deltas = time_index - start_
-            else:
-                time_deltas = time_index - start_
-
-            col_name = f"time_since_{start_}"
-            Xt[col_name] = time_deltas
-
-        if self.to_numeric and self.positive_only:
-            Xt = Xt.clip(lower=0)
-
-        if self.keep_original_columns:
-            Xt = pd.concat([X, Xt], axis=1, copy=True)
-
-        return Xt
-
-    @classmethod
-    def get_test_params(cls, parameter_set="default"):
-        """Return testing parameter settings for the estimator.
-
-        Parameters
-        ----------
-        parameter_set : str, default="default"
-            Name of the set of test parameters to return, for use in tests. If no
-            special parameters are defined for a value, will return `"default"` set.
-            There are currently no reserved values for transformers.
-
-        Returns
-        -------
-        params : dict or list of dict, default = {}
-            Parameters to create testing instances of the class
-            Each dict are parameters to construct an "interesting" test instance, i.e.,
-            `MyClass(**params)` or `MyClass(**params[i])` creates a valid test instance.
-            `create_test_instance` uses the first (or only) dictionary in `params`
-        """
-        return [
-            {"start": None, "to_numeric": True},
-            {
-                "start": ["2000-01-01", "2000-01-02"],
-                "to_numeric": False,
-                "positive_only": True,
-            },
-        ]
-
-
-def _get_period_diff_as_int(x: pd.PeriodIndex, y: pd.PeriodIndex) -> pd.Index:
-    return x.astype("int64") - y.astype("int64")
-
-
-def _remove_digits_from_str(x: str) -> str:
-    return x.translate({ord(k): None for k in digits})
-
-
-def _get_time_index(X: pd.DataFrame) -> pd.PeriodIndex | pd.DatetimeIndex:
-    """Get time index from single and multi-index dataframes."""
-    if isinstance(X.index, pd.MultiIndex):
-        time_index = X.index.get_level_values(-1)
-    else:
-        time_index = X.index
-    return time_index
diff --git a/docs/api_reference/transformations.rst b/docs/api_reference/transformations.rst
index dfd04d89..07fae82a 100644
--- a/docs/api_reference/transformations.rst
+++ b/docs/api_reference/transformations.rst
@@ -218,14 +218,14 @@ Lagging
 
     Lag
 
-Element-wise transforms
+Series transforms
 ~~~~~~~~~~~~~~~~~~~~~~~
 
 These transformations apply a function element-wise.
 
 Depending on the transformer, the transformation parameters can be fitted.
 
-.. currentmodule:: aeon.transformations.boxcox
+.. currentmodule:: aeon.transformations.series._boxcox
 
 .. autosummary::
     :toctree: auto_generated/
@@ -264,7 +264,7 @@ Detrending
     ConditionalDeseasonalizer
     STLTransformer
 
-.. currentmodule:: aeon.transformations.clear_sky
+.. currentmodule:: aeon.transformations.series._clear_sky
 
 .. autosummary::
     :toctree: auto_generated/
@@ -284,14 +284,6 @@ Filtering and denoising
 
     BKFilter
 
-.. currentmodule:: aeon.transformations.kalman_filter
-
-.. autosummary::
-    :toctree: auto_generated/
-    :template: class.rst
-
-    KalmanFilterTransformer
-
 .. currentmodule:: aeon.transformations.theta
 
 .. autosummary::
@@ -354,14 +346,6 @@ Seasonality and Date-Time Features
 
     DateTimeFeatures
 
-.. currentmodule:: aeon.transformations.time_since
-
-.. autosummary::
-    :toctree: auto_generated/
-    :template: class.rst
-
-    TimeSince
-
 .. currentmodule:: aeon.transformations.fourier
 
 .. autosummary::
diff --git a/docs/getting_started.md b/docs/getting_started.md
index 167acfdf..630f9cc3 100644
--- a/docs/getting_started.md
+++ b/docs/getting_started.md
@@ -398,7 +398,7 @@ yourself, you will need to `pip install statsmodels` and `pip install pmdarima`)
 ```{code-block} python
 >>> import numpy as np
 >>> from aeon.datasets import load_airline
->>> from aeon.transformations.boxcox import BoxCoxTransformer
+>>> from aeon.transformations.series._boxcox import BoxCoxTransformer
 >>> from aeon.transformations.detrend import Deseasonalizer
 >>> from aeon.forecasting.arima import ARIMA
 >>> from aeon.forecasting.compose import TransformedTargetForecaster
@@ -494,7 +494,7 @@ to ARIMA order values for the forecasting pipeline we created in the previous ex
 ...     ForecastingGridSearchCV,
 ... )
 >>> from aeon.forecasting.arima import ARIMA
->>> from aeon.transformations.boxcox import BoxCoxTransformer
+>>> from aeon.transformations.series._boxcox import BoxCoxTransformer
 >>> from aeon.transformations.detrend import Deseasonalizer
 ...
 >>> y = load_airline()
diff --git a/examples/transformations/transformations.ipynb b/examples/transformations/transformations.ipynb
index 2e62aa3e..2aa195bc 100644
--- a/examples/transformations/transformations.ipynb
+++ b/examples/transformations/transformations.ipynb
@@ -90,7 +90,7 @@
    ],
    "source": [
     "from aeon.datasets import load_airline\n",
-    "from aeon.transformations.boxcox import BoxCoxTransformer\n",
+    "from aeon.transformations._legacy._boxcox import _BoxCoxTransformer as BoxCoxTransformer\n",
     "from aeon.transformations.summarize import SummaryTransformer\n",
     "from aeon.visualisation import plot_series\n",
     "\n",
diff --git a/pyproject.toml b/pyproject.toml
index 13cd24a5..20064796 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -60,7 +60,6 @@ dependencies = [
 all_extras = [
     "cloudpickle",
     "esig>=0.9.7,<0.9.8.3; python_version < '3.11'",
-    "filterpy>=1.4.5",
     "gluonts>=0.12.4",
     "h5py",
     "imbalanced-learn",


Test patch:
diff --git a/aeon/forecasting/compose/tests/test_bagging.py b/aeon/forecasting/compose/tests/test_bagging.py
index 537b698f..1c6b6b17 100644
--- a/aeon/forecasting/compose/tests/test_bagging.py
+++ b/aeon/forecasting/compose/tests/test_bagging.py
@@ -7,8 +7,8 @@ from aeon.datasets import load_airline
 from aeon.forecasting.compose import BaggingForecaster
 from aeon.forecasting.compose._bagging import _calculate_data_quantiles
 from aeon.forecasting.naive import NaiveForecaster
+from aeon.transformations._legacy._boxcox import _LogTransformer
 from aeon.transformations.bootstrap import STLBootstrapTransformer
-from aeon.transformations.boxcox import LogTransformer
 from aeon.utils.validation._dependencies import _check_soft_dependencies
 
 y = load_airline()
@@ -18,7 +18,7 @@ y = load_airline()
     not _check_soft_dependencies("statsmodels", severity="none"),
     reason="skip test if required soft dependency for BaggingForecaster not available",
 )
-@pytest.mark.parametrize("transformer", [LogTransformer, NaiveForecaster])
+@pytest.mark.parametrize("transformer", [_LogTransformer, NaiveForecaster])
 def test_bagging_forecaster_transformer_type_error(transformer):
     """Test that the right exception is raised for invalid transformer."""
     with pytest.raises(TypeError) as ex:
@@ -37,7 +37,7 @@ def test_bagging_forecaster_transformer_type_error(transformer):
     not _check_soft_dependencies("statsmodels", severity="none"),
     reason="skip test if required soft dependency not available",
 )
-@pytest.mark.parametrize("forecaster", [LogTransformer])
+@pytest.mark.parametrize("forecaster", [_LogTransformer])
 def test_bagging_forecaster_forecaster_type_error(forecaster):
     """Test that the right exception is raised for invalid forecaster."""
     with pytest.raises(TypeError) as ex:
diff --git a/aeon/forecasting/compose/tests/test_pipeline.py b/aeon/forecasting/compose/tests/test_pipeline.py
index 21f8f588..49a56f5b 100644
--- a/aeon/forecasting/compose/tests/test_pipeline.py
+++ b/aeon/forecasting/compose/tests/test_pipeline.py
@@ -94,7 +94,7 @@ def test_nesting_pipelines():
     from aeon.testing.utils.scenarios_forecasting import (
         ForecasterFitPredictUnivariateWithX,
     )
-    from aeon.transformations.boxcox import LogTransformer
+    from aeon.transformations._legacy._boxcox import _LogTransformer as LogTransformer
     from aeon.transformations.compose import OptionalPassthrough
     from aeon.transformations.detrend import Detrender
 
diff --git a/aeon/testing/mock_estimators/tests/test_mock_forecasters.py b/aeon/testing/mock_estimators/tests/test_mock_forecasters.py
index 1fb1863a..f9041d9a 100644
--- a/aeon/testing/mock_estimators/tests/test_mock_forecasters.py
+++ b/aeon/testing/mock_estimators/tests/test_mock_forecasters.py
@@ -22,7 +22,7 @@ from aeon.testing.mock_estimators._mock_forecasters import (
 )
 from aeon.testing.utils.deep_equals import deep_equals
 from aeon.transformations.base import BaseTransformer
-from aeon.transformations.boxcox import BoxCoxTransformer
+from aeon.transformations.series._boxcox import BoxCoxTransformer
 
 y_series = load_airline().iloc[:-5]
 y_frame = y_series.to_frame()
diff --git a/aeon/testing/test_config.py b/aeon/testing/test_config.py
index e85bc825..bf43eac7 100644
--- a/aeon/testing/test_config.py
+++ b/aeon/testing/test_config.py
@@ -21,10 +21,10 @@ if os.environ.get("CICD_RUNNING") == "1":
     import aeon.testing.utils._cicd_numba_caching  # noqa: F401
 
 EXCLUDE_ESTIMATORS = [
-    "BoxCoxTransformer",
+    "_BoxCoxTransformer",
     "TimeBinAggregate",
     "PartialAutoCorrelationTransformer",
-    "LogTransformer",
+    "_LogTransformer",
     "ReverseAugmenter",
     "RandomSamplesAugmenter",
     "SqrtTransformer",
diff --git a/aeon/transformations/series/tests/test_boxcox.py b/aeon/transformations/series/tests/test_boxcox.py
index 1c263225..fa98c9ab 100644
--- a/aeon/transformations/series/tests/test_boxcox.py
+++ b/aeon/transformations/series/tests/test_boxcox.py
@@ -47,7 +47,7 @@ def test_guerrero_against_r_implementation(bounds, r_lambda):
 
     Testing lambda values estimated by the R implementation of the Guerrero method
     https://github.com/robjhyndman/forecast/blob/master/R/guerrero.R
-    against the guerrero method in BoxCoxTransformer.
+    against the guerrero method in _BoxCoxTransformer.
     R code to generate the hardcoded value for bounds=(-1, 2) used in the test
     ('Airline.csv' contains the data from 'load_airline()'):
         airline_file <- read.csv(file = 'Airline.csv')[,c('Passengers')]
diff --git a/aeon/transformations/tests/test_compose.py b/aeon/transformations/tests/test_compose.py
index 2e8e3e7e..c813bf2b 100644
--- a/aeon/transformations/tests/test_compose.py
+++ b/aeon/transformations/tests/test_compose.py
@@ -11,7 +11,7 @@ from aeon.testing.data_generation import get_examples
 from aeon.testing.mock_estimators import MockTransformer
 from aeon.testing.utils.deep_equals import deep_equals
 from aeon.testing.utils.estimator_checks import _assert_array_almost_equal
-from aeon.transformations.boxcox import LogTransformer
+from aeon.transformations._legacy._boxcox import _LogTransformer
 from aeon.transformations.collection.pad import PaddingTransformer
 from aeon.transformations.compose import (
     ColumnConcatenator,
@@ -185,9 +185,9 @@ def test_pipeline_column_vectorization():
 def test_pipeline_inverse():
     """Tests that inverse composition works, with inverse skips. Also see #3084."""
     X = load_airline()
-    t = LogTransformer() * Imputer()
+    t = _LogTransformer() * Imputer()
 
-    # LogTransformer has inverse_transform, and does not skip inverse transform
+    # _LogTransformer has inverse_transform, and does not skip inverse transform
     # therefore, pipeline should also not skip inverse transform, and have capability
     assert t.get_tag("capability:inverse_transform")
     assert not t.get_tag("skip-inverse-transform")
diff --git a/aeon/transformations/tests/test_fitintransform.py b/aeon/transformations/tests/test_fitintransform.py
index b7994e37..c8c13510 100644
--- a/aeon/transformations/tests/test_fitintransform.py
+++ b/aeon/transformations/tests/test_fitintransform.py
@@ -10,7 +10,7 @@ from aeon.transformations.series._boxcox import BoxCoxTransformer
 
 
 def test_transform_fitintransform():
-    """Test fit/transform against BoxCoxTransformer."""
+    """Test fit/transform against _BoxCoxTransformer."""
     X_train = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
     X_test = np.array([5, 4, 5, 4, 5, 4, 5, 4, 5, 4])
     fitintransform = FitInTransform(BoxCoxTransformer())