Repository: aeon-toolkit/aeon
Pull request #286 (2023-04-12 15:16:55)

[MNT] pandas>=1.5.3,<2.1.0
lower bound see #276 
upper bound see #274 


Patch:
diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
index 9d8e96e2..809d1985 100644
--- a/.github/FUNDING.yml
+++ b/.github/FUNDING.yml
@@ -1,12 +1,12 @@
 # These are supported funding model platforms
 
-github: scikit-time
-patreon: # replace with username
-open_collective: # replace with username
-ko_fi: # replace with username
-tidelift: # replace with username
-community_bridge: # replace with username
-liberapay: # replace with username
-issuehunt: # replace with username
-otechie: # replace with username
-custom: # replace with custom URLs e.g., ['link1', 'link2']
+github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
+patreon: # Replace with a single Patreon username
+open_collective: # Replace with a single Open Collective username
+ko_fi: # Replace with a single Ko-fi username
+tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
+community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
+liberapay: # Replace with a single Liberapay username
+issuehunt: # Replace with a single IssueHunt username
+otechie: # Replace with a single Otechie username
+custom: # Replace with custom URLs e.g., ['link1', 'link2']
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
index b7d8da7b..c9bf2f11 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.md
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -1,18 +1,18 @@
 ---
 name: "\U0001F41B Bug report"
-about: Create a report to help us improve
+about: Report a bug currently impacting aeon.
 title: "[BUG]"
 labels: bug
-assignees: ''
-
 ---
 
-**Describe the bug**
+#### Describe the bug
+
 <!--
 A clear and concise description of what the bug is.
 -->
 
-**To Reproduce**
+#### To Reproduce
+
 <!--
 Add a Minimal, Complete, and Verifiable example (for more details, see e.g. https://stackoverflow.com/help/mcve
 
@@ -23,17 +23,19 @@ If the code is too long, feel free to put it in a public gist and link it in the
 <Paste your code here>
 ```
 
-**Expected behavior**
+#### Expected behavior
+
 <!--
 A clear and concise description of what you expected to happen.
 -->
 
-**Additional context**
+#### Additional context
+
 <!--
 Add any other context about the problem here.
 -->
 
-**Versions**
+#### Versions
 <details>
 
 <!--
diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml
index 82dc1218..5930ab1e 100644
--- a/.github/ISSUE_TEMPLATE/config.yml
+++ b/.github/ISSUE_TEMPLATE/config.yml
@@ -1,7 +1,7 @@
 contact_links:
   - name: "\U0001F4AC All other questions and general chat"
-    url: https://join.slack.com/t/scikit-timeworkspace/shared_invite/zt-1pkhua342-W_W24XuAZt2JZU1GniK2YA
+    url: https://join.slack.com/t/aeon-toolkit/shared_invite/zt-1plkevy4x-vAg1dAUXcuoR38FjY9nxzg
     about: Chat with the aeon community on Slack
   - name: "\u2709\uFE0F Code of Conduct incident reporting"
     url: https://www.aeon-toolkit.org/en/latest/get_involved/code_of_conduct.html#incident-reporting-guidelines
-    about: Report an incident to the Code of Conduct committee
+    about: Report an incident to the Code of Conduct Committee
diff --git a/.github/ISSUE_TEMPLATE/doc_improvement.md b/.github/ISSUE_TEMPLATE/doc_improvement.md
index 63d56fae..e9a4b3ff 100644
--- a/.github/ISSUE_TEMPLATE/doc_improvement.md
+++ b/.github/ISSUE_TEMPLATE/doc_improvement.md
@@ -1,10 +1,8 @@
 ---
 name: "\U0001F4D6 Documentation improvement"
-about: Create a report to help us improve the documentation. Alternatively you can just open a pull request with the suggested change.
+about: Create a report to help us improve the aeon documentation.
 title: "[DOC]"
 labels: documentation
-assignees: ''
-
 ---
 
 #### Describe the issue linked to the documentation
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
index f89493f5..943a8216 100644
--- a/.github/ISSUE_TEMPLATE/feature_request.md
+++ b/.github/ISSUE_TEMPLATE/feature_request.md
@@ -1,20 +1,30 @@
 ---
 name: "\u2728 Feature request"
-about: Suggest an idea for this project
-title: '[ENH]'
+about: Suggest a new algorithm or idea for aeon.
+title: "[ENH]"
 labels: enhancement
-assignees: ''
-
 ---
 
-**Is your feature request related to a problem? Please describe.**
+#### Is your feature request related to a problem? Please describe.
+
+<!--
 A clear and concise description of what the problem is.
+-->
+
+#### Describe the solution you'd like
 
-**Describe the solution you'd like**
+<!--
 A clear and concise description of what you want to happen, ideally taking into consideration the existing toolbox design, classes and methods.
+-->
 
-**Describe alternatives you've considered**
+#### Describe alternatives you've considered, if relevant
+
+<!--
 A clear and concise description of any alternative solutions or features you've considered.
+-->
+
+#### Additional context
 
-**Additional context**
-Add any other context or screenshots about the feature request here.
+<!--
+Add any other context about the problem here.
+-->
diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
index 8edabf51..8faace28 100644
--- a/.github/PULL_REQUEST_TEMPLATE.md
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -1,19 +1,19 @@
 <!--
-Thanks for contributing a pull request! Please ensure you have taken a look
-at our contribution guide: https://github.com/aeon-toolkit/aeon/blob/main/CONTRIBUTING.md
+Thanks for contributing a pull request! Please ensure you have taken a look at our contribution guide: https://github.com/aeon-toolkit/aeon/blob/main/CONTRIBUTING.md
+
+Feel free to delete sections of this template if they do not apply to your PR, avoid submitting a blank template or empty sections.
 -->
 
 #### Reference Issues/PRs
+
 <!--
 Example: Fixes #1234. See also #3456.
 
-Please use keywords (e.g., Fixes) to create link to the issues or pull requests
-you resolved, so that they will automatically be closed when your pull request
-is merged. See https://github.com/blog/1506-closing-issues-via-pull-requests
+Please use keywords (e.g., Fixes) to create link to the issues or pull requests you resolved, so that they will automatically be closed when your pull request is merged. See https://github.com/blog/1506-closing-issues-via-pull-requests
 -->
 
-
 #### What does this implement/fix? Explain your changes.
+
 <!--
 A clear and concise description of what you have implemented.
 -->
@@ -21,24 +21,29 @@ A clear and concise description of what you have implemented.
 #### Does your contribution introduce a new dependency? If yes, which one?
 
 <!--
-If your contribution does add a new hard dependency, we may suggest to initially develop your contribution in a separate companion package in https://github.com/aeon/ to keep external dependencies of the core aeon package to a minimum.
+If your contribution does add a dependency, we may suggest adding it as an optional/soft dependency to keep external dependencies of the core aeon package to a minimum.
 -->
 
 #### What should a reviewer concentrate their feedback on?
 
-<!-- This section is particularly useful if you have a pull request that is still in development. You can guide the reviews to focus on the parts that are ready for their comments. We suggest using bullets (indicated by * or -) and filled checkboxes [x] here -->
+<!--
+This section is particularly useful if you have a pull request that is still in development. You can guide the reviews to focus on the parts that are ready for their comments. We suggest using bullets (indicated by * or -) and filled checkboxes [x] here
+-->
 
 #### Did you add any tests for the change?
 
-<!-- This section is useful if you have added a test in addition to the existing ones. This will ensure that further changes to these files won't introduce the same kind of bug. It is considered good practice to add tests with newly added code to enforce the fact that the code actually works. This will reduce the chance of introducing logical bugs.
+<!--
+This section is useful if you have added a test in addition to the existing ones. This will ensure that further changes to these files won't introduce the same kind of bug. It is considered good practice to add tests with newly added code to enforce the fact that the code actually works. This will reduce the chance of introducing logical bugs.
 -->
 
 #### Any other comments?
+
 <!--
 Please be aware that we are a loose team of volunteers so patience is necessary; assistance handling other issues is very welcome. We value all user contributions, no matter how minor they are. If we are slow to review, either the pull request needs some benchmarking, tinkering, convincing, etc. or more likely the reviewers are simply busy. In either case, we ask for your understanding during the review process.
 -->
 
-#### PR checklist
+### PR checklist
+
 <!--
 Please go through the checklist below. Please feel free to remove points if they are not applicable.
 -->
@@ -47,10 +52,7 @@ Please go through the checklist below. Please feel free to remove points if they
 - [ ] I've added myself to the [list of contributors](https://github.com/aeon-toolkit/aeon/blob/main/.all-contributorsrc).
 - [ ] Optionally, I've updated aeon's [CODEOWNERS](https://github.com/aeon-toolkit/aeon/blob/main/CODEOWNERS) to receive notifications about future changes to these files.
 - [ ] The PR title starts with either [ENH], [MNT], [DOC], or [BUG] indicating whether the PR topic is related to enhancement, maintenance, documentation, or bug.
-
-##### For new estimators
-- [ ] I've added the estimator to the online documentation.
-- [ ] I've updated the existing example notebooks or provided a new one to showcase how my estimator works.
+- [ ] For new estimators, I've added the estimator to the online documentation.
 
 
 <!--
diff --git a/.github/release-drafter.yml b/.github/release-drafter.yml
deleted file mode 100644
index 425dbbe7..00000000
--- a/.github/release-drafter.yml
+++ /dev/null
@@ -1,25 +0,0 @@
-name-template: 'v$NEXT_PATCH_VERSION'
-tag-template: 'v$NEXT_PATCH_VERSION'
-categories:
-  - title: '🚀 Features'
-    labels:
-      - 'feature'
-      - 'enhancement'
-  - title: '🐛 Bug Fixes'
-    labels:
-      - 'fix'
-      - 'bugfix'
-      - 'bug'
-  - title: '🧰 Maintenance'
-    label:
-      - 'chore'
-      - 'maintenance'
-      - 'refactor'
-      - 'documentation'
-
-template: |
-  ## What's New
-
-  $CHANGES
-
-  All contributors: $CONTRIBUTORS
diff --git a/.github/release.yml b/.github/release.yml
index c013f46e..12fc604f 100644
--- a/.github/release.yml
+++ b/.github/release.yml
@@ -1,23 +1,21 @@
 changelog:
-  exclude:
-    authors:
-      - octocat
-      - dependabot
   categories:
     - title: '🚀 Features'
       labels:
-        - 'feature'
         - 'enhancement'
+        - 'implementing algorithms'
+        - 'implementing framework'
+        - 'interfacing algorithms'
     - title: '🐛 Bug Fixes'
       labels:
-        - 'fix'
-        - 'bugfix'
         - 'bug'
     - title: '🧰 Maintenance'
       label:
-        - 'chore'
         - 'maintenance'
         - 'refactor'
+        - 'testing'
+    - title: '📖 Documentation'
+      label:
         - 'documentation'
     - title: Other Changes
       labels:
diff --git a/.github/workflows/wheels.yml b/.github/workflows/release.yml
similarity index 67%
rename from .github/workflows/wheels.yml
rename to .github/workflows/release.yml
index bb9dde63..dc33395e 100644
--- a/.github/workflows/wheels.yml
+++ b/.github/workflows/release.yml
@@ -1,13 +1,28 @@
-name: Build wheels and publish to PyPI
+name: Release
 
 on:
   release:
-    types: [published]
+    types:
+      - published
 
 jobs:
+  check_manifest:
+    runs-on: ubuntu-22.04
+
+    steps:
+      - uses: actions/checkout@v3
+
+      - uses: actions/setup-python@v4
+        with:
+          python-version: "3.10"
+
+      - uses: pre-commit/action@v3.0.0
+        with:
+          extra_args: check-manifest --hook-stage manual
+
   build_wheels:
-    name: Build wheels
-    runs-on: ubuntu-20.04
+    needs: check_manifest
+    runs-on: ubuntu-22.04
 
     steps:
       - uses: actions/checkout@v3
@@ -16,39 +31,41 @@ jobs:
         with:
           python-version: '3.10'
 
-      - name: Build wheel
+      - name: Build project
         run: |
           python -m pip install build
-          python -m build --wheel --sdist --outdir wheelhouse
+          python -m build
 
-      - name: Store wheels
-        uses: actions/upload-artifact@v2
+      - name: Store build files
+        uses: actions/upload-artifact@v3
         with:
-          name: wheels
-          path: wheelhouse/*
+          name: dist
+          path: dist/*
 
   test_unix_wheels:
     needs: build_wheels
     name: Test wheels on ${{ matrix.os }} with ${{ matrix.python-version }}
     runs-on: ${{ matrix.os }}
+
     strategy:
       matrix:
-        os: [ubuntu-20.04, macOS-11]
+        os: [ubuntu-22.04, macOS-12]
         python-version: ['3.8', '3.9', '3.10']
 
     steps:
       - uses: actions/checkout@v3
+
       - uses: actions/setup-python@v4
         with:
           python-version: ${{ matrix.python-version }}
 
-      - uses: actions/download-artifact@v2
+      - uses: actions/download-artifact@v3
         with:
-          name: wheels
-          path: wheelhouse
+          name: dist
+          path: dist
 
       - name: Get wheel filename
-        run: echo "WHEELNAME=$(ls ./wheelhouse/aeon-*none-any.whl)" >> $GITHUB_ENV
+        run: echo "WHEELNAME=$(ls ./dist/aeon-*none-any.whl)" >> $GITHUB_ENV
 
       - name: Install wheel and extras
         run: python -m pip install "${{ env.WHEELNAME }}[all_extras,dev]"
@@ -59,31 +76,26 @@ jobs:
   test_windows_wheels:
     needs: build_wheels
     name: Test wheels on ${{ matrix.os }} with ${{ matrix.python-version }}
-    runs-on: windows-2019
+    runs-on: windows-2022
     strategy:
       matrix:
         include:
           # Window 64 bit
-          - os: windows-2019
+          - os: windows-2022
             python: 38
             python-version: '3.8'
             bitness: 64
             platform_id: win_amd64
-          - os: windows-2019
+          - os: windows-2022
             python: 39
             python-version: '3.9'
             bitness: 64
             platform_id: win_amd64
-          - os: windows-2019
+          - os: windows-2022
             python: 310
             python-version: '3.10'
             bitness: 64
             platform_id: win_amd64
-          - os: windows-2019
-            python: 39
-            python-version: 3.9
-            bitness: 64
-            platform_id: win_amd64
 
     steps:
       - uses: actions/checkout@v3
@@ -97,19 +109,19 @@ jobs:
       - run: conda --version
       - run: which python
 
-      - uses: actions/download-artifact@v2
+      - uses: actions/download-artifact@v3
         with:
-          name: wheels
-          path: wheelhouse
+          name: dist
+          path: dist
 
       - name: Install conda libpython
         run: conda install -c anaconda -n test -y libpython
 
       - name: Display downloaded artifacts
-        run: ls -l wheelhouse
+        run: ls -l dist
 
       - name: Get wheel filename
-        run: echo "WHEELNAME=$(ls ./wheelhouse/aeon-*none-any.whl)" >> $env:GITHUB_ENV
+        run: echo "WHEELNAME=$(ls ./dist/aeon-*none-any.whl)" >> $env:GITHUB_ENV
 
       - name: Activate conda env
         run: conda activate test
@@ -128,19 +140,16 @@ jobs:
           python -m pytest
 
   upload_wheels:
-    name: Upload wheels to PyPI
     runs-on: ubuntu-latest
     needs: [build_wheels,test_unix_wheels,test_windows_wheels]
 
     steps:
-      - uses: actions/download-artifact@v2
+      - uses: actions/download-artifact@v3
         with:
-          name: wheels
-          path: wheelhouse
+          name: dist
+          path: dist
 
       - name: Publish package to PyPI
         uses: pypa/gh-action-pypi-publish@release/v1
         with:
-          user: ${{ secrets.PYPI_USERNAME }}
-          password: ${{ secrets.PYPI_PASSWORD }}
-          packages_dir: wheelhouse/
+          password: ${{ secrets.PYPI_TOKEN }}
diff --git a/Makefile b/Makefile
index 84aa582d..4a5a5b8f 100644
--- a/Makefile
+++ b/Makefile
@@ -17,12 +17,6 @@ help:
 		 awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-15s\033[0m\
 		 %s\n", $$1, $$2}'
 
-release: ## Make a release
-	python3 $(BUILD_TOOLS)/make_release.py
-
-install: ## Install for the current user using the default python command
-	python3 setup.py build_ext --inplace && python setup.py install --user
-
 test: ## Run unit tests
 	-rm -rf ${TEST_DIR}
 	mkdir -p ${TEST_DIR}
@@ -30,6 +24,8 @@ test: ## Run unit tests
 	cp setup.cfg ${TEST_DIR}
 	python -m pytest
 
+tests: test
+
 test_softdeps: ## Run unit tests to check soft dependency handling in estimators
 	-rm -rf ${TEST_DIR}
 	mkdir -p ${TEST_DIR}
@@ -45,35 +41,3 @@ test_softdeps_full: ## Run all non-suite unit tests without soft dependencies
 	cp setup.cfg ${TEST_DIR}
 	cd ${TEST_DIR}
 	python -m pytest -v --showlocals --durations=20 -k 'not TestAll' $(PYTESTOPTIONS) --ignore=aeon/utils/tests/test_mlflow_aeon_model_export.py
-
-tests: test
-
-clean: ## Clean build dist and egg directories left after install
-	rm -rf ./dist
-	rm -rf ./build
-	rm -rf ./pytest_cache
-	rm -rf ./htmlcov
-	rm -rf ./junit
-	rm -rf ./$(PACKAGE).egg-info
-	rm -rf coverage.xml
-	rm -f MANIFEST
-	rm -rf ./wheelhouse/*
-	find . -type f -iname "*.so" -delete
-	find . -type f -iname '*.pyc' -delete
-	find . -type d -name '__pycache__' -empty -delete
-
-dist: ## Make Python source distribution
-	python3 setup.py sdist bdist_wheel
-
-build:
-	python -m build --sdist --wheel --outdir wheelhouse
-
-docs: doc
-
-doc: ## Build documentation with Sphinx
-	$(MAKE) -C $(DOC_DIR) html
-
-nb: clean
-	rm -rf .venv || true
-	python3 -m venv .venv
-	. .venv/bin/activate && python -m pip install .[all_extras,binder] && ./build_tools/run_examples.sh
diff --git a/aeon/classification/distance_based/_shape_dtw.py b/aeon/classification/distance_based/_shape_dtw.py
index d9f235a2..96a25e62 100644
--- a/aeon/classification/distance_based/_shape_dtw.py
+++ b/aeon/classification/distance_based/_shape_dtw.py
@@ -16,6 +16,7 @@ from aeon.classification.distance_based._time_series_neighbors import (
     KNeighborsTimeSeriesClassifier,
 )
 from aeon.datatypes import convert
+from aeon.datatypes._panel._convert import from_3d_numpy_to_nested
 from aeon.transformations.panel.dictionary_based._paa import PAA
 from aeon.transformations.panel.dwt import DWTTransformer
 from aeon.transformations.panel.hog1d import HOG1DTransformer
@@ -144,10 +145,8 @@ class ShapeDTW(BaseClassifier):
         # Perform preprocessing on params.
         if not (isinstance(self.shape_descriptor_function, str)):
             raise TypeError(
-                "shape_descriptor_function must be an 'str'. \
-                            Found '"
-                + type(self.shape_descriptor_function).__name__
-                + "' instead."
+                f"shape_descriptor_function must be an 'str'. Found "
+                f"{type(self.shape_descriptor_function).__name__} instead."
             )
 
         if self.metric_params is None:
@@ -246,9 +245,9 @@ class ShapeDTW(BaseClassifier):
         # the test/training data. It extracts the subsequences
         # and then performs the shape descriptor function on
         # each subsequence.
-        X = convert(X, from_type="numpy3D", to_type="nested_univ")
         X = self.sw.transform(X)
-
+        # Temporary until conversion complete
+        X = from_3d_numpy_to_nested(X)
         # Feed X into the appropriate shape descriptor function
         X = self._generate_shape_descriptors(X)
 
diff --git a/aeon/clustering/base.py b/aeon/clustering/base.py
index 1875941a..91314f5b 100644
--- a/aeon/clustering/base.py
+++ b/aeon/clustering/base.py
@@ -29,9 +29,8 @@ class BaseClusterer(BaseEstimator, ABC):
     """
 
     _tags = {
-        "X_inner_mtype": "numpy3D",  # which type do _fit/_predict accept, usually
-        # this is either "numpy3D" or "nested_univ" (nested pd.DataFrame). Other
-        # types are allowable, see datatypes/panel/_registry.py for options.
+        "X_inner_mtype": "numpy3D",
+        # other types are allowable, see datatypes/panel/_registry.py for options.
         "capability:multivariate": False,
         "capability:unequal_length": False,
         "capability:missing_values": False,
@@ -52,10 +51,8 @@ class BaseClusterer(BaseEstimator, ABC):
         Parameters
         ----------
         X : Training time series instances to cluster. np.ndarray (2d or 3d array of
-        shape (n_instances, series_length) or shape (n_instances, n_dimensions,
-        series_length)) or pd.DataFrame (where each column is a dimension, each cell
-        is a pd.Series (any number of dimensions, equal or unequal length series)).
-        Converted to type _tags["X_inner_mtype"]
+        shape (n_instances, series_length) or shape (n_instances, n_channels,
+        series_length)).
         y: ignored, exists for API consistency reasons.
 
         Returns
@@ -89,9 +86,7 @@ class BaseClusterer(BaseEstimator, ABC):
         Parameters
         ----------
         X : np.ndarray (2d or 3d array of shape (n_instances, series_length) or shape
-            (n_instances, n_dimensions, series_length)) or pd.DataFrame (where each
-            column is a dimension, each cell is a pd.Series (any number of dimensions,
-            equal or unequal length series)).
+            (n_instances, n_channels, series_length)).
             Time series instances to predict their cluster indexes.
         y: ignored, exists for API consistency reasons.
 
@@ -112,9 +107,7 @@ class BaseClusterer(BaseEstimator, ABC):
         Parameters
         ----------
         X : np.ndarray (2d or 3d array of shape (n_instances, series_length) or shape
-            (n_instances, n_dimensions, series_length)) or pd.DataFrame (where each
-            column is a dimension, each cell is a pd.Series (any number of dimensions,
-            equal or unequal length series)).
+            (n_instances, n_channels, series_length)).
             Time series instances to train clusterer and then have indexes each belong
             to return.
         y: ignored, exists for API consistency reasons.
@@ -138,12 +131,8 @@ class BaseClusterer(BaseEstimator, ABC):
         ----------
         X : guaranteed to be of a type in self.get_tag("X_inner_mtype")
             if self.get_tag("X_inner_mtype") = "numpy3D":
-                3D np.ndarray of shape = [n_instances, n_dimensions, series_length]
-            if self.get_tag("X_inner_mtype") = "nested_univ":
-                pd.DataFrame with each column a dimension, each cell a pd.Series
+                3D np.ndarray of shape = [n_instances, n_channels, series_length]
             for list of other mtypes, see datatypes.SCITYPE_REGISTER
-            for specifications, see examples/AA_datatypes_and_datasets.ipynb
-
 
         Returns
         -------
@@ -162,9 +151,7 @@ class BaseClusterer(BaseEstimator, ABC):
         Parameters
         ----------
         X : np.ndarray (2d or 3d array of shape (n_instances, series_length) or shape
-            (n_instances, n_dimensions, series_length)) or pd.DataFrame (where each
-            column is a dimension, each cell is a pd.Series (any number of dimensions,
-            equal or unequal length series)).
+            (n_instances, n_channels, series_length)).
             Time series instances to train clusterer and then have indexes each belong
             to return.
         y: ignored, exists for API consistency reasons.
@@ -189,11 +176,8 @@ class BaseClusterer(BaseEstimator, ABC):
         ----------
         X : guaranteed to be of a type in self.get_tag("X_inner_mtype")
             if self.get_tag("X_inner_mtype") = "numpy3D":
-                3D np.ndarray of shape = [n_instances, n_dimensions, series_length]
-            if self.get_tag("X_inner_mtype") = "nested_univ":
-                pd.DataFrame with each column a dimension, each cell a pd.Series
+                3D np.ndarray of shape = [n_instances, n_channels, series_length]
             for list of other mtypes, see datatypes.SCITYPE_REGISTER
-            for specifications, see examples/AA_datatypes_and_datasets.ipynb
 
         Returns
         -------
@@ -223,10 +207,8 @@ class BaseClusterer(BaseEstimator, ABC):
         Parameters
         ----------
         X : np.ndarray (2d or 3d array of shape (n_instances, series_length) or shape
-            (n_instances,n_dimensions,series_length)) or pd.Dataframe.
-            Time series instances to predict their cluster indexes. If data is not
-            equal length a pd.Dataframe given, if another other type of data a
-            np.ndarray given.
+            (n_instances,n_channels,series_length)).
+            Time series instances to predict their cluster indexes.
         y: ignored, exists for API consistency reasons.
 
         Returns
@@ -243,9 +225,8 @@ class BaseClusterer(BaseEstimator, ABC):
         Parameters
         ----------
         X : np.ndarray (2d or 3d array of shape (n_instances, series_length) or shape
-            (n_instances,n_dimensions,series_length)) or pd.Dataframe.
-            Training time series instances to cluster. If data is not equal length a
-            pd.Dataframe given, if another other type of data a np.ndarray given.
+            (n_instances,n_channels,series_length)).
+            Training time series instances to cluster.
 
         Returns
         -------
@@ -295,18 +276,7 @@ class BaseClusterer(BaseEstimator, ABC):
 
     @staticmethod
     def _initial_conversion(X: Any) -> TimeSeriesInstances:
-        """Format data as valid panel mtype of the data.
-
-        Parameters
-        ----------
-        X: Any
-            Data to convert to panel mtype.
-
-        Returns
-        -------
-        X: np.ndarray (at least 2d) or pd.Dataframe or List[pd.Dataframe]
-            Converted X.
-        """
+        """Convert 2D numpy to 3D if necessary."""
         if isinstance(X, np.ndarray) and X.ndim == 2:
             X = X.reshape(X.shape[0], 1, X.shape[1])
         return X
@@ -319,14 +289,12 @@ class BaseClusterer(BaseEstimator, ABC):
         Parameters
         ----------
         X : np.ndarray (2d or 3d array of shape (n_instances, series_length) or shape
-            (n_instances,n_dimensions,series_length)) or nested pd.DataFrame (
-            n_instances,n_dimensions).
+            (n_instances,n_channels,series_length)).
             Training time series instances to cluster.
 
         Returns
         -------
-        X : np.ndarray (3d of shape (n_instances,n_dimensions,series_length)) or
-            pd.Dataframe (n_instances,n_dimensions).
+        X : np.ndarray (3d of shape (n_instances,n_channels,series_length)).
             Converted X ready for _fit.
 
         Raises
@@ -342,9 +310,7 @@ class BaseClusterer(BaseEstimator, ABC):
         if not X_valid:
             raise TypeError(
                 f"X is not of a supported input data type."
-                f"X must be of type np.ndarray or pd.DataFrame, found {type(X)}"
-                f"Use datatypes.check_is_mtype to check conformance with "
-                f"specifications."
+                f"X must be of type np.ndarray, found {type(X)}."
             )
         n_cases = X_metadata["n_instances"]
         if n_cases < enforce_min_instances:
diff --git a/aeon/forecasting/varmax.py b/aeon/forecasting/varmax.py
index 12c42754..ae80d709 100644
--- a/aeon/forecasting/varmax.py
+++ b/aeon/forecasting/varmax.py
@@ -8,6 +8,9 @@ import warnings
 import pandas as pd
 
 from aeon.forecasting.base.adapters import _StatsModelsAdapter
+from aeon.utils.validation._dependencies import _check_soft_dependencies
+
+_check_soft_dependencies("pandas<2.0.0", severity="warning")
 
 
 class VARMAX(_StatsModelsAdapter):
@@ -216,6 +219,7 @@ class VARMAX(_StatsModelsAdapter):
         "X-y-must-have-same-index": True,
         "enforce_index_type": None,
         "capability:pred_int": False,
+        "python_dependencies": "pandas<2.0.0",  # needs to be fixed with pandas==2.0.0
     }
 
     def __init__(
diff --git a/aeon/transformations/panel/dictionary_based/_paa.py b/aeon/transformations/panel/dictionary_based/_paa.py
index bb9164c7..cef62b4b 100644
--- a/aeon/transformations/panel/dictionary_based/_paa.py
+++ b/aeon/transformations/panel/dictionary_based/_paa.py
@@ -1,8 +1,7 @@
 # -*- coding: utf-8 -*-
 """Piecewise Aggregate Approximation Transformer (PAA)."""
-import pandas as pd
+import numpy as np
 
-from aeon.datatypes._panel._convert import from_nested_to_2d_array
 from aeon.transformations.base import BaseTransformer
 
 __author__ = "MatthewMiddlehurst"
@@ -11,93 +10,89 @@ __author__ = "MatthewMiddlehurst"
 class PAA(BaseTransformer):
     """Piecewise Aggregate Approximation Transformer (PAA).
 
-    (PAA) Piecewise Aggregate Approximation Transformer, as described in
-    Eamonn Keogh, Kaushik Chakrabarti, Michael Pazzani, and Sharad Mehrotra.
-    Dimensionality reduction for fast similarity search in large time series
-    databases.
-    Knowledge and information Systems, 3(3), 263-286, 2001.
-    For each series reduce the dimensionality to num_intervals, where each
-    value is the mean of values in
-    the interval.
-
-    TO DO: pythonise it to make it more efficient. Maybe check vs this version
-            http://vigne.sh/posts/piecewise-aggregate-approx/
-    Could have: Tune the interval size in fit somehow?
+    (PAA) Piecewise Aggregate Approximation Transformer, as described in [1]. For
+    each series reduce the dimensionality to num_intervals, where each value is the
+    mean of values in the interval.
 
     Parameters
     ----------
-    num_intervals   : int, dimension of the transformed data (default 8)
+    n_intervals   : int, dimension of the transformed data (default 8)
+
+    Notes
+    -----
+    [1]  Eamonn Keogh, Kaushik Chakrabarti, Michael Pazzani, and Sharad Mehrotra.
+    Dimensionality reduction for fast similarity search in large time series
+    databases. Knowledge and information Systems, 3(3), 263-286, 2001.
+
+    Examples
+    --------
+    >>> from aeon.transformations.panel.dictionary_based import PAA
+    >>> import numpy as np
+    >>> data = np.array([[[1,2,3,4,5,6,7,8,9,10]],[[5,5,5,5,5,5,5,5,5,5]]])
+    >>> paa = PAA(n_intervals=2)
+    >>> data2 = paa.fit_transform(data)
     """
 
     _tags = {
-        "scitype:transform-input": "Series",
-        # what is the scitype of X: Series, or Panel
         "scitype:transform-output": "Series",
-        # what scitype is returned: Primitives, Series, Panel
-        "scitype:instancewise": True,  # is this an instance-wise transform?
-        "X_inner_mtype": "nested_univ",  # which mtypes do _fit/_predict support for X?
-        "y_inner_mtype": "None",  # which mtypes do _fit/_predict support for X?
+        "scitype:instancewise": True,
+        "X_inner_mtype": "numpy3D",
+        "y_inner_mtype": "None",
     }
 
-    def __init__(self, num_intervals=8):
-        self.num_intervals = num_intervals
+    def __init__(self, n_intervals=8):
+        self.n_intervals = n_intervals
         super(PAA, self).__init__()
 
     def set_num_intervals(self, n):
         """Set self.num_intervals to n."""
-        self.num_intervals = n
+        self.n_intervals = n
 
-    # todo: looks like this just loops over series instances
-    # so should be refactored to work on Series directly
     def _transform(self, X, y=None):
         """Transform data.
 
         Parameters
         ----------
-        X : nested pandas DataFrame of shape [n_instances, n_dims]
-            Nested dataframe with multivariate time-series in cells.
+        X : 3D np.ndarray of shape = [n_instances, n_channels, series_length]
+            collection of time series to transform
+        y : ignored argument for interface compatibility
 
         Returns
         -------
-        dims: Pandas data frame with first dimension in column zero,
-              second in column one etc.
+        X : 3D np.ndarray of shape = [n_instances, n_channels, series_length]
+            collection of transformed time series
         """
         # Get information about the dataframe
-        num_atts = len(X.iloc[0, 0])
-        col_names = X.columns
+        # PAA acts on each dimension, so its best to reshape prior to transform
+        n_cases, n_channels, series_length = X.shape
+        _X = np.swapaxes(X, 0, 1)
 
         # Check the parameters are appropriate
-        self._check_parameters(num_atts)
+        self._check_parameters(series_length)
 
         # On each dimension, perform PAA
-        dataFrames = []
-        for x in col_names:
-            dataFrames.append(self._perform_paa_along_dim(pd.DataFrame(X[x])))
-
-        # Combine the dimensions together
-        result = pd.concat(dataFrames, axis=1, sort=False)
-        result.columns = col_names
+        channels = []
+        for i in range(n_channels):
+            channels.append(self._perform_paa_along_dim(_X[i]))
+        result = np.array(channels)
+        result = np.swapaxes(result, 0, 1)
 
         return result
 
     def _perform_paa_along_dim(self, X):
-        X = from_nested_to_2d_array(X, return_numpy=True)
-
-        num_atts = X.shape[1]
-        num_insts = X.shape[0]
-        dims = pd.DataFrame()
+        n_cases, series_length = X.shape
         data = []
 
-        for i in range(num_insts):
+        for i in range(n_cases):
             series = X[i, :]
 
             frames = []
             current_frame = 0
             current_frame_size = 0
-            frame_length = num_atts / self.num_intervals
+            frame_length = series_length / self.n_intervals
             frame_sum = 0
 
-            for n in range(num_atts):
+            for n in range(series_length):
                 remaining = frame_length - current_frame_size
 
                 if remaining > 1:
@@ -115,16 +110,14 @@ class PAA(BaseTransformer):
                     current_frame_size = 1 - remaining
 
             # if the last frame was lost due to double imprecision
-            if current_frame == self.num_intervals - 1:
+            if current_frame == self.n_intervals - 1:
                 frames.append(frame_sum / frame_length)
 
-            data.append(pd.Series(frames))
-
-        dims[0] = data
+            data.append(frames)
 
-        return dims
+        return data
 
-    def _check_parameters(self, num_atts):
+    def _check_parameters(self, series_length):
         """Check parameters of PAA.
 
         Function for checking the values of parameters inserted into PAA.
@@ -135,20 +128,15 @@ class PAA(BaseTransformer):
         ------
         ValueError or TypeError if a parameters input is invalid.
         """
-        if isinstance(self.num_intervals, int):
-            if self.num_intervals <= 0:
-                raise ValueError(
-                    "num_intervals must have the \
-                                  value of at least 1"
-                )
-            if self.num_intervals > num_atts:
+        if isinstance(self.n_intervals, int):
+            if self.n_intervals <= 0:
+                raise ValueError("num_intervals must have the value of at least 1")
+            if self.n_intervals > series_length:
                 raise ValueError(
-                    "num_intervals cannot be higher \
-                                  than the time series length."
+                    "num_intervals cannot be higher than the time series length."
                 )
         else:
             raise TypeError(
-                "num_intervals must be an 'int'. Found '"
-                + type(self.num_intervals).__name__
-                + "' instead."
+                f"num_intervals must be an 'int'. Found"
+                f" {type(self.n_intervals).__name__} instead."
             )
diff --git a/aeon/transformations/panel/dictionary_based/_sax.py b/aeon/transformations/panel/dictionary_based/_sax.py
index 27a006e6..fcc3f1b7 100644
--- a/aeon/transformations/panel/dictionary_based/_sax.py
+++ b/aeon/transformations/panel/dictionary_based/_sax.py
@@ -135,7 +135,7 @@ class SAX(BaseTransformer):
 
             split = scipy.stats.zscore(split, axis=1)
 
-            paa = PAA(num_intervals=self.word_length)
+            paa = PAA(n_intervals=self.word_length)
             data = pd.DataFrame()
             data[0] = [pd.Series(x, dtype=np.float32) for x in split]
             patterns = paa.fit_transform(data)
diff --git a/aeon/transformations/panel/segment.py b/aeon/transformations/panel/segment.py
index e306e4ef..a5080123 100644
--- a/aeon/transformations/panel/segment.py
+++ b/aeon/transformations/panel/segment.py
@@ -389,10 +389,17 @@ class SlidingWindowSegmenter(BaseTransformer):
 
     Returns
     -------
-        df : pandas dataframe of shape
-             [n_instances, n_timepoints]
+        np.array [n_instances, n_timepoints, window_length]
 
     Proposed in the ShapeDTW algorithm.
+
+    Examples
+    --------
+    >>> from aeon.transformations.panel.segment import SlidingWindowSegmenter
+    >>> import numpy as np
+    >>> data = np.array([[[1, 2, 3, 4, 5, 6, 7, 8]], [[5, 5, 5, 5, 5, 5, 5, 5]]])
+    >>> seggy = SlidingWindowSegmenter(window_length=4)
+    >>> data2 = seggy.fit_transform(data)
     """
 
     _tags = {
@@ -401,32 +408,32 @@ class SlidingWindowSegmenter(BaseTransformer):
         "scitype:transform-input": "Series",
         # what is the scitype of X: Series, or Panel
         "scitype:transform-output": "Series",
-        # what scitype is returned: Primitives, Series, Panel
-        "scitype:instancewise": False,  # is this an instance-wise transform?
-        "X_inner_mtype": "nested_univ",  # which mtypes do _fit/_predict support for X?
-        "y_inner_mtype": "None",  # which mtypes do _fit/_predict support for y?
+        "scitype:instancewise": False,
+        "X_inner_mtype": "numpy3D",
+        "y_inner_mtype": "None",
     }
 
     def __init__(self, window_length=5):
         self.window_length = window_length
-        super(SlidingWindowSegmenter, self).__init__()
+        super(SlidingWindowSegmenter, self).__init__(_output_convert=False)
 
     def _transform(self, X, y=None):
         """Transform time series.
 
         Parameters
         ----------
-        X : nested pandas DataFrame of shape [n_instances, n_features]
-            each cell of X must contain pandas.Series
-            Data to be transformed
+        X : 3D np.ndarray of shape = [n_cases, 1, series_length]
+            collection of time series to transform
         y : ignored argument for interface compatibility
 
         Returns
         -------
-        dims: a pandas data frame of shape = [n_instances, n_timepoints]
+        X : 3D np.ndarray of shape = [n_cases, series_length, window_length]
+            windowed series
         """
         # get the number of attributes and instances
-        X = check_X(X, enforce_univariate=True, coerce_to_numpy=True)
+        if X.shape[1] > 1:
+            raise ValueError("Segmenter does not support multivariate")
         X = X.squeeze(1)
 
         n_timepoints = X.shape[1]
@@ -447,17 +454,7 @@ class SlidingWindowSegmenter(BaseTransformer):
         # Extract subsequences
         for i in range(n_instances):
             subsequences[i] = self._extract_subsequences(padded_data[i], n_timepoints)
-
-        # Convert this into a panda's data frame
-        df = pd.DataFrame()
-        for i in range(len(subsequences)):
-            inst = subsequences[i]
-            data = []
-            for j in range(len(inst)):
-                data.append(pd.Series(inst[j]))
-            df[i] = data
-
-        return df.transpose()
+        return np.array(subsequences)
 
     def _extract_subsequences(self, instance, n_timepoints):
         """Extract a set of subsequences from a list of instances.
diff --git a/build_tools/make_release.py b/build_tools/make_release.py
deleted file mode 100644
index ec957d76..00000000
--- a/build_tools/make_release.py
+++ /dev/null
@@ -1,280 +0,0 @@
-#!/usr/bin/env python3 -u
-# -*- coding: utf-8 -*-
-# copyright: aeon developers, BSD-3-Clause License (see LICENSE file)
-"""
-Do-nothing script for making a release
-
-This idea comes from here:
-- https://blog.danslimmon.com/2019/07/15/do-nothing-scripting-the-key-to
--gradual-automation/
-
-The script is adapted from:
-- https://github.com/alan-turing-institute/CleverCSV/blob/master
-/make_release.py
-"""
-
-__author__ = ["Markus Löning"]
-
-import codecs
-import os
-import re
-import webbrowser
-
-import colorama
-
-ROOT_DIR = os.path.abspath(os.path.dirname(__file__)).replace("build_tools", "")
-PACKAGE_NAME = "aeon"
-
-
-class URLs:
-    DOCS_LOCAL = "file://" + os.path.realpath(
-        os.path.join(ROOT_DIR, "docs/_build/html/index.html")
-    )
-    DOCS_ONLINE = "https://www.aeon-toolkit.org"
-    PYPI = f"https://pypi.org/simple/{PACKAGE_NAME}/"
-
-
-def read(*parts):
-    # intentionally *not* adding an encoding option to open, See:
-    #   https://github.com/pypa/virtualenv/issues/201#issuecomment-3145690
-    with codecs.open(os.path.join(ROOT_DIR, *parts), "r") as fp:
-        return fp.read()
-
-
-def find_version(*file_paths):
-    version_file = read(*file_paths)
-    version_match = re.search(r"^__version__ = ['\"]([^'\"]*)['\"]", version_file, re.M)
-    if version_match:
-        return version_match.group(1)
-    else:
-        raise RuntimeError("Unable to find version string.")
-
-
-def open_website(website):
-    webbrowser.open(website, new=1)
-
-
-def colored(msg, color=None, style=None):
-    colors = {
-        "red": colorama.Fore.RED,
-        "green": colorama.Fore.GREEN,
-        "cyan": colorama.Fore.CYAN,
-        "yellow": colorama.Fore.YELLOW,
-        "magenta": colorama.Fore.MAGENTA,
-        None: "",
-    }
-    styles = {
-        "bright": colorama.Style.BRIGHT,
-        "dim": colorama.Style.DIM,
-        None: "",
-    }
-    pre = colors[color] + styles[style]
-    post = colorama.Style.RESET_ALL
-    return f"{pre}{msg}{post}"
-
-
-def cprint(msg, color=None, style=None):
-    """Coloured printing"""
-    print(colored(msg, color=color, style=style))  # noqa
-
-
-def wait_for_enter():
-    input(colored("\nPress Enter to continue", style="dim"))
-    print()  # noqa
-
-
-class Step:
-    def pre(self, context):
-        pass
-
-    def post(self, context):
-        wait_for_enter()
-
-    def run(self, context):
-        try:
-            self.pre(context)
-            self.action(context)
-            self.post(context)
-        except KeyboardInterrupt:
-            cprint("\nInterrupted.", color="red")
-            raise SystemExit(1)
-
-    @staticmethod
-    def instruct(msg):
-        cprint(msg, color="green")
-
-    def print_run(self, msg):
-        cprint("Run:", color="cyan", style="bright")
-        self.print_cmd(msg)
-
-    @staticmethod
-    def print_cmd(msg):
-        cprint("\t" + msg, color="cyan", style="bright")
-
-    @staticmethod
-    def do_cmd(cmd):
-        cprint(f"Going to run: {cmd}", color="magenta", style="bright")
-        wait_for_enter()
-        os.system(cmd)
-
-    def action(self, context):
-        raise NotImplementedError("abstract method")
-
-
-class ConfirmGitStatus(Step):
-    def __init__(self, branch):
-        self.branch = branch
-
-    def action(self, context):
-        self.instruct(
-            f"Make sure you're on: {self.branch}, you're local "
-            f"branch is up-to-date, and all new changes are merged "
-            f"in."
-        )
-        self.do_cmd(f"git checkout {self.branch}")
-        self.do_cmd("git pull")
-
-
-class UpdateChangelog(Step):
-    def action(self, context):
-        self.instruct(f"Update CHANGELOG for version: {context['version']}")
-
-
-class UpdateReadme(Step):
-    def action(self, context):
-        self.instruct(f"Update README for version: {context['version']}")
-
-
-class UpdateVersion(Step):
-    def action(self, context):
-        self.instruct("Update __init__.py with new version")
-
-    def post(self, context):
-        wait_for_enter()
-        context["version"] = find_version(context["package_name"], "__init__.py")
-
-
-class MakeClean(Step):
-    def action(self, context):
-        self.do_cmd("make clean")
-
-
-class MakeDocs(Step):
-    def action(self, context):
-        self.do_cmd("make docs")
-
-
-class MakeDist(Step):
-    def action(self, context):
-        self.do_cmd("make dist")
-
-
-class UploadToTestPyPI(Step):
-    def action(self, context):
-        self.instruct("Upload to TestPyPI")
-        cmd = "twine upload --repository-url https://test.pypi.org/legacy/ dist/*"
-        self.do_cmd(cmd)
-
-
-class InstallFromTestPyPI(Step):
-    def action(self, context):
-        self.instruct("Check installation from TestPyPI")
-        self.do_cmd(
-            f"sh build_tools/check_install_from_test_pypi.sh {context['version']}"
-        )
-
-
-class CheckVersionNumber(Step):
-    def action(self, context):
-        self.instruct(
-            f"Ensure that the following command gives version: {context['version']}"
-        )
-        self.do_cmd(
-            f"python -c 'import {context['package_name']}; print("
-            f"{context['package_name']}.__version__)'"
-        )
-
-
-class GitTagRelease(Step):
-    def action(self, context):
-        self.instruct("Tag version as a release")
-        self.do_cmd(f"git tag v{context['version']}")
-
-
-class GitTagPreRelease(Step):
-    def action(self, context):
-        self.instruct("Tag version as a pre-release (increment as needed)")
-        self.print_run(f"git tag v{context['version']}-rc.1")
-
-
-class PushToGitHub(Step):
-    def action(self, context):
-        self.instruct("Add and commit to git, then push to GitHub")
-
-
-class CheckCIStatus(Step):
-    def action(self, context):
-        self.instruct("Wait for CI to complete and check status")
-
-
-class CheckOnlineDocs(Step):
-    def action(self, context):
-        self.instruct("Check online docs")
-        open_website(URLs.DOCS_ONLINE)
-
-
-class CheckLocalDocs(Step):
-    def action(self, context):
-        self.instruct("Check local docs")
-        open_website(URLs.DOCS_LOCAL)
-
-
-class CheckPyPIFiles(Step):
-    def action(self, context):
-        self.instruct("Check PyPI files")
-        open_website(URLs.PYPI)
-
-
-class PushTagToGitHub(Step):
-    def action(self, context):
-        self.do_cmd(f"git push origin v{context['version']}")
-
-
-def main():
-    colorama.init()
-    steps = [
-        # prepare and run final checks
-        ConfirmGitStatus(branch="main"),
-        MakeClean(),
-        UpdateVersion(),
-        CheckVersionNumber(),
-        UpdateReadme(),
-        UpdateChangelog(),
-        MakeDocs(),
-        CheckLocalDocs(),
-        MakeDist(),
-        UploadToTestPyPI(),
-        InstallFromTestPyPI(),
-        PushToGitHub(),
-        CheckCIStatus(),
-        # check pre-release online
-        # GitTagPreRelease(),
-        # PushTagToGitHub(),
-        # make release
-        GitTagRelease(),
-        PushTagToGitHub(),
-        CheckCIStatus(),
-        CheckOnlineDocs(),
-        CheckPyPIFiles(),
-    ]
-    context = dict()
-    context["package_name"] = PACKAGE_NAME
-    context["version"] = find_version(context["package_name"], "__init__.py")
-    context["testdir"] = "temp/"
-    for step in steps:
-        step.run(context)
-    cprint("\nDone!", color="yellow", style="bright")
-
-
-if __name__ == "__main__":
-    main()
diff --git a/docs/developer_guide/release.rst b/docs/developer_guide/release.rst
index 8daf5c1f..dfdcdc29 100644
--- a/docs/developer_guide/release.rst
+++ b/docs/developer_guide/release.rst
@@ -131,21 +131,3 @@ Generally, release notes should follow the general pattern of previous release n
 * maintenance
 * bugfixes
 * all contributor credits
-
-
-Legacy build tools
-------------------
-
-We no longer use the legacy build tools using the make file.
-
-To run the legacy release workflow, e.g., for development purposes, run
-
-.. code:: bash
-
-   make release
-
-This calls
-`build_tools/make_release.py <https://github.com/aeon-toolkit/aeon/blob/main/build_tools/make_release.py>`__
-that will guide you through the release process.
-
-IMPORTANT: when running the legacy build tools, ensure to not accidentally push a release tag to the ``aeon`` repo.
diff --git a/examples/01_forecasting.ipynb b/examples/01_forecasting.ipynb
index ae7dcf04..3676ae5d 100644
--- a/examples/01_forecasting.ipynb
+++ b/examples/01_forecasting.ipynb
@@ -5132,58 +5132,6 @@
     "mean_absolute_percentage_error(y_test, y_pred, symmetric=False)"
    ]
   },
-  {
-   "cell_type": "markdown",
-   "metadata": {
-    "tags": []
-   },
-   "source": [
-    "### 2.3.6 AutoARIMA from [StatsForecast](https://github.com/Nixtla/statsforecast)<a class=\"anchor\" id=\"section_2_3_6\"></a>\n",
-    "\n",
-    "`aeon` interfaces `StatsForecast` for its `AutoARIMA` class models. `AutoARIMA` is an automatically tuned `ARIMA` variant that obtains the optimal pdq parameters automatically:"
-   ]
-  },
-  {
-   "cell_type": "code",
-   "execution_count": 243,
-   "metadata": {},
-   "outputs": [
-    {
-     "data": {
-      "text/plain": [
-       "0.04093539044441262"
-      ]
-     },
-     "execution_count": 243,
-     "metadata": {},
-     "output_type": "execute_result"
-    },
-    {
-     "data": {
-      "image/png": "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",
-      "text/plain": [
-       "<Figure size 1152x288 with 1 Axes>"
-      ]
-     },
-     "metadata": {
-      "needs_background": "light"
-     },
-     "output_type": "display_data"
-    }
-   ],
-   "source": [
-    "# StatsForecastAutoARIMA does not work with pandas 2.0.0 (yet). If so, pls make a PR.\n",
-    "if pd.__version__ < \"2.0.0\":\n",
-    "    from aeon.forecasting.statsforecast import StatsForecastAutoARIMA\n",
-    "\n",
-    "    forecaster = StatsForecastAutoARIMA(sp=12)\n",
-    "\n",
-    "    forecaster.fit(y_train)\n",
-    "    y_pred = forecaster.predict(fh)\n",
-    "    plot_series(y_train, y_test, y_pred, labels=[\"y_train\", \"y_test\", \"y_pred\"])\n",
-    "    mean_absolute_percentage_error(y_pred, y_test)"
-   ]
-  },
   {
    "cell_type": "markdown",
    "metadata": {},
diff --git a/pyproject.toml b/pyproject.toml
index e050a6f3..59f862de 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -38,13 +38,13 @@ classifiers = [
 ]
 requires-python = ">=3.8,<3.11"
 dependencies = [
+    "attrs>=19.2.0", # see #282
     "deprecated>=1.2.13",
     "numba>=0.55",
     "numpy>=1.21.0,<1.25",
-    "pandas<2.1.0",
+    "pandas>=1.5.3,<2.1.0",
     "scikit-learn>=1.0.0,<1.3.0",
     "scipy<2.0.0,>=1.2.0",
-    "attrs>=19.2.0", # see #282
     "packaging>=20.0",
 ]
 
@@ -66,7 +66,7 @@ all_extras = [
     "pyod>=0.8.0",
     "scikit_posthocs>=0.6.5",
     "seaborn>=0.11.0",
-    "statsforecast>=0.5.2",
+    # "statsforecast>=0.5.2",
     "statsmodels>=0.12.1",
     "stumpy>=1.5.1",
     "tbats>=1.1.0",


Test patch:
diff --git a/aeon/clustering/tests/test_k_means.py b/aeon/clustering/tests/test_k_means.py
index 8c9f69d4..f730b45e 100644
--- a/aeon/clustering/tests/test_k_means.py
+++ b/aeon/clustering/tests/test_k_means.py
@@ -149,8 +149,8 @@ def test_kmeans():
 )
 def test_kmeans_dba():
     """Test implementation of Kmeans using dba."""
-    X_train, y_train = load_basic_motions(split="train", return_type="nested_univ")
-    X_test, y_test = load_basic_motions(split="test", return_type="nested_univ")
+    X_train, y_train = load_basic_motions(split="train")
+    X_test, y_test = load_basic_motions(split="test")
 
     num_test_values = 5
 
@@ -162,12 +162,12 @@ def test_kmeans_dba():
         init_algorithm="kmeans++",
         metric="dtw",
     )
-    train_predict = kmeans.fit_predict(X_train.head(num_test_values))
+    train_predict = kmeans.fit_predict(X_train[0:num_test_values])
     train_mean_score = metrics.rand_score(y_train[0:num_test_values], train_predict)
 
-    test_mean_result = kmeans.predict(X_test.head(num_test_values))
+    test_mean_result = kmeans.predict(X_test[0:num_test_values])
     mean_score = metrics.rand_score(y_test[0:num_test_values], test_mean_result)
-    proba = kmeans.predict_proba(X_test.head(num_test_values))
+    proba = kmeans.predict_proba(X_test[0:num_test_values])
 
     assert np.array_equal(test_mean_result, expected_results["dba"])
     assert mean_score == expected_score["dba"]
diff --git a/aeon/forecasting/tests/test_varmax.py b/aeon/forecasting/tests/test_varmax.py
index 61c856f3..dd682092 100644
--- a/aeon/forecasting/tests/test_varmax.py
+++ b/aeon/forecasting/tests/test_varmax.py
@@ -22,7 +22,12 @@ df = pd.DataFrame(
 
 
 @pytest.mark.skipif(
-    not _check_soft_dependencies("statsmodels", severity="none"),
+    not all(
+        (
+            _check_soft_dependencies("statsmodels", severity="none"),
+            _check_soft_dependencies("pandas<2.0.0", severity="none"),
+        )
+    ),
     reason="skip test if required soft dependency not available",
 )
 def test_VARMAX_against_statsmodels():
@@ -50,7 +55,12 @@ def test_VARMAX_against_statsmodels():
 
 
 @pytest.mark.skipif(
-    not _check_soft_dependencies("statsmodels", severity="none"),
+    not all(
+        (
+            _check_soft_dependencies("statsmodels", severity="none"),
+            _check_soft_dependencies("pandas<2.0.0", severity="none"),
+        )
+    ),
     reason="skip test if required soft dependency not available",
 )
 def test_VARMAX_against_statsmodels_with_exog():
diff --git a/aeon/tests/_config.py b/aeon/tests/_config.py
index f45217ef..5239ddc8 100644
--- a/aeon/tests/_config.py
+++ b/aeon/tests/_config.py
@@ -108,6 +108,7 @@ EXCLUDED_TESTS = {
         "test_fit_does_not_overwrite_hyper_params",
         "test_methods_have_no_side_effects",
     ],
+    "SlidingWindowSegmenter": ["test_fit_transform_output"],
     # sth is not quite right with the RowTransformer-s changing state,
     #   but these are anyway on their path to deprecation, see #2370
     "SeriesToSeriesRowTransformer": ["test_non_state_changing_method_contract"],
diff --git a/aeon/transformations/panel/dictionary_based/tests/test_paa.py b/aeon/transformations/panel/dictionary_based/tests/test_paa.py
index 1e02e6f2..34a12e62 100644
--- a/aeon/transformations/panel/dictionary_based/tests/test_paa.py
+++ b/aeon/transformations/panel/dictionary_based/tests/test_paa.py
@@ -14,16 +14,16 @@ def test_bad_input_args(bad_num_intervals):
     X = np.array([[[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]]])
     if not isinstance(bad_num_intervals, int):
         with pytest.raises(TypeError):
-            PAA(num_intervals=bad_num_intervals).fit(X).transform(X)
+            PAA(n_intervals=bad_num_intervals).fit(X).transform(X)
     else:
         with pytest.raises(ValueError):
-            PAA(num_intervals=bad_num_intervals).fit(X).transform(X)
+            PAA(n_intervals=bad_num_intervals).fit_transform(X)
 
 
 # Check the transformer has changed the data correctly.
 def test_output_of_transformer():
     X = np.array([[[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]]])
-    p = PAA(num_intervals=3).fit(X)
+    p = PAA(n_intervals=3).fit(X)
     res = p.transform(X)
     orig = np.array([[[2.2, 5.5, 8.8]]])
     np.testing.assert_array_almost_equal(res, orig)
@@ -32,7 +32,7 @@ def test_output_of_transformer():
 def test_output_dimensions():
     # test with univariate
     X = np.random.rand(10, 1, 12)
-    p = PAA(num_intervals=5).fit(X)
+    p = PAA(n_intervals=5).fit(X)
     res = p.transform(X)
     assert res.shape[0] == 10 and res.shape[1] == 1 and res.shape[2] == 5
 
@@ -40,7 +40,7 @@ def test_output_dimensions():
 # This is to check that PAA produces the same result along each dimension
 def test_paa_performs_correcly_along_each_dim():
     X = np.array([[[1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]]])
-    p = PAA(num_intervals=3).fit(X)
+    p = PAA(n_intervals=3).fit(X)
     res = p.transform(X)
     orig = [[[2.2, 5.5, 8.8], [2.2, 5.5, 8.8]]]
     np.testing.assert_array_almost_equal(res, orig)
diff --git a/aeon/transformations/panel/tests/test_sliding_window_segmenter_transformer.py b/aeon/transformations/panel/tests/test_sliding_window_segmenter_transformer.py
index 871ee406..9c413f2f 100644
--- a/aeon/transformations/panel/tests/test_sliding_window_segmenter_transformer.py
+++ b/aeon/transformations/panel/tests/test_sliding_window_segmenter_transformer.py
@@ -5,11 +5,9 @@ __authors__ = ["mloning"]
 
 
 import numpy as np
-import pandas as pd
 import pytest
 
 from aeon.transformations.panel.segment import SlidingWindowSegmenter
-from aeon.utils._testing.panel import _make_nested_from_array
 
 
 # Check that exception is raised for bad window length.
@@ -18,56 +16,55 @@ from aeon.utils._testing.panel import _make_nested_from_array
 @pytest.mark.parametrize("bad_window_length", ["str", 1.2, -1.2, -1, {}])
 def test_bad_input_args(bad_window_length):
     """Test that bad inputs raise value error."""
-    X = _make_nested_from_array(np.ones(10), n_instances=10, n_columns=1)
-
+    X = np.ones(shape=(10, 1, 10))
     if not isinstance(bad_window_length, int):
         with pytest.raises(TypeError):
-            SlidingWindowSegmenter(window_length=bad_window_length).fit(X).transform(X)
+            SlidingWindowSegmenter(window_length=bad_window_length).fit_transform(X)
     else:
         with pytest.raises(ValueError):
-            SlidingWindowSegmenter(window_length=bad_window_length).fit(X).transform(X)
+            SlidingWindowSegmenter(window_length=bad_window_length).fit_transform(X)
 
 
 # Check the transformer has changed the data correctly.
 def test_output_of_transformer():
     """Test correct output of SlidingWindowSegmenter."""
-    X = _make_nested_from_array(
-        np.array([1, 2, 3, 4, 5, 6]), n_instances=1, n_columns=1
-    )
-
+    X = np.array([[[1, 2, 3, 4, 5, 6]]])
     st = SlidingWindowSegmenter(window_length=1).fit(X)
     res = st.transform(X)
-    orig = convert_list_to_dataframe([[1.0], [2.0], [3.0], [4.0], [5.0], [6.0]])
-    assert check_if_dataframes_are_equal(res, orig)
+    orig = np.array([[[1.0], [2.0], [3.0], [4.0], [5.0], [6.0]]])
+    np.testing.assert_array_equal(res, orig)
 
     st = SlidingWindowSegmenter(window_length=5).fit(X)
     res = st.transform(X)
-    orig = convert_list_to_dataframe(
+    orig = np.array(
         [
-            [1.0, 1.0, 1.0, 2.0, 3.0],
-            [1.0, 1.0, 2.0, 3.0, 4.0],
-            [1.0, 2.0, 3.0, 4.0, 5.0],
-            [2.0, 3.0, 4.0, 5.0, 6.0],
-            [3.0, 4.0, 5.0, 6.0, 6.0],
-            [4.0, 5.0, 6.0, 6.0, 6.0],
+            [
+                [1.0, 1.0, 1.0, 2.0, 3.0],
+                [1.0, 1.0, 2.0, 3.0, 4.0],
+                [1.0, 2.0, 3.0, 4.0, 5.0],
+                [2.0, 3.0, 4.0, 5.0, 6.0],
+                [3.0, 4.0, 5.0, 6.0, 6.0],
+                [4.0, 5.0, 6.0, 6.0, 6.0],
+            ]
         ]
     )
-
-    assert check_if_dataframes_are_equal(res, orig)
+    np.testing.assert_array_equal(res, orig)
 
     st = SlidingWindowSegmenter(window_length=10).fit(X)
     res = st.transform(X)
-    orig = convert_list_to_dataframe(
+    orig = np.array(
         [
-            [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 2.0, 3.0, 4.0, 5.0],
-            [1.0, 1.0, 1.0, 1.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0],
-            [1.0, 1.0, 1.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 6.0],
-            [1.0, 1.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 6.0, 6.0],
-            [1.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 6.0, 6.0, 6.0],
-            [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 6.0, 6.0, 6.0, 6.0],
+            [
+                [1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 2.0, 3.0, 4.0, 5.0],
+                [1.0, 1.0, 1.0, 1.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0],
+                [1.0, 1.0, 1.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 6.0],
+                [1.0, 1.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 6.0, 6.0],
+                [1.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 6.0, 6.0, 6.0],
+                [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 6.0, 6.0, 6.0, 6.0],
+            ]
         ]
     )
-    assert check_if_dataframes_are_equal(res, orig)
+    np.testing.assert_array_equal(res, orig)
 
 
 @pytest.mark.parametrize(
@@ -75,41 +72,13 @@ def test_output_of_transformer():
 )
 def test_output_dimensions(time_series_length, window_length):
     """Test output dimensions of SlidingWindowSegmenter."""
-    X = _make_nested_from_array(
-        np.ones(time_series_length), n_instances=10, n_columns=1
-    )
-
-    st = SlidingWindowSegmenter(window_length=window_length).fit(X)
-    res = st.transform(X)
+    X = np.ones(shape=(10, 1, time_series_length))
+    st = SlidingWindowSegmenter(window_length=window_length)
+    res = st.fit_transform(X)
 
     # get the dimension of the generated dataframe.
-    corr_time_series_length = res.iloc[0, 0].shape[0]
-    num_rows = res.shape[0]
-    num_cols = res.shape[1]
-
-    assert corr_time_series_length == window_length
-    assert num_rows == 10
-    assert num_cols == time_series_length
-
-
-def convert_list_to_dataframe(list_to_convert):
-    """Convert list into a pandas data frame."""
-    df = pd.DataFrame()
-    for i in range(len(list_to_convert)):
-        inst = list_to_convert[i]
-        data = []
-        data.append(pd.Series(inst))
-        df[i] = data
-
-    return df
-
-
-def check_if_dataframes_are_equal(df1, df2):
-    """Check that pandas DataFrames are equal."""
-    from pandas.testing import assert_frame_equal
+    n_cases, n_channels, series_length = res.shape
 
-    try:
-        assert_frame_equal(df1, df2)
-        return True
-    except AssertionError:
-        return False
+    assert series_length == window_length
+    assert n_cases == 10
+    assert n_channels == time_series_length
diff --git a/build_tools/check_install_from_test_pypi.sh b/build_tools/check_install_from_test_pypi.sh
deleted file mode 100644
index a99deec0..00000000
--- a/build_tools/check_install_from_test_pypi.sh
+++ /dev/null
@@ -1,35 +0,0 @@
-#!/bin/bash
-
-# Helper script to download and install aeon from test PyPI to check wheel
-# and upload prior to new release
-
-set -e
-
-# Version to test, passed as input argument to script
-VERSION=$1
-
-# Make temporary directory
-echo "Making test directory ..."
-mkdir "$HOME"/testdir
-cd "$HOME"/testdir
-
-# Create test environment
-echo "Creating test environment ..."
-
-# shellcheck disable=SC1091
-source "$(conda info --base)"/etc/profile.d/conda.sh  # set up conda
-conda create -n aeon_testenv python=3.9
-conda activate aeon_testenv
-
-# Install from test PyPI
-echo "Installing aeon from Test PyPI ..."
-pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple aeon=="$VERSION"
-echo "Successfully installed aeon from Test PyPI."
-
-# Clean up test directory and environment
-echo "Cleaning up ..."
-conda deactivate
-conda remove -n aeon_testenv --all -y
-rm -r "$HOME"/testdir
-
-echo "Done."