Repository: ruleminer/InterpreTS (language: python)

Issue:
Full functionality of the feature "length" with tests and examples



Discussion / hints:

Fix patch:
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000..d4ddca4
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,7 @@
+{
+    "python.analysis.extraPaths": [
+        "./src/utils",
+        "./src/core",
+        "./src"
+    ]
+}
\ No newline at end of file
diff --git a/README.md b/README.md
deleted file mode 100644
index 27093de..0000000
--- a/README.md
+++ /dev/null
@@ -1,2 +0,0 @@
-# InterpreTS
-Feature extraction from time series to support the creation of interpretable and explainable predictive models
diff --git a/docs/INSTALLATION.md b/docs/INSTALLATION.md
new file mode 100644
index 0000000..bd29f0e
--- /dev/null
+++ b/docs/INSTALLATION.md
@@ -0,0 +1,42 @@
+# Installation Guide for InterpreTS
+Follow the steps below to install InterpreTS and its dependencies.
+
+## Requirements
+Python 3.8 or higher
+- [`pandas`](https://github.com/pandas-dev/pandas)
+- [`numpy`](https://github.com/numpy/numpy)
+  
+## Steps
+1. Clone the repository: Clone the InterpreTS repository to your local machine:
+   
+```python
+git clone https://github.com/ruleminer/InterpreTS.git
+cd time_series_feature_extractor
+```
+
+2. Install dependencies: Install the required packages listed in the `requirements.txt` file:
+
+```python
+pip install -r requirements.txt
+```
+
+3. Install InterpreTS: Run the following command to install InterpreTS:
+
+```python
+pip install .
+```
+
+## Verifying Installation
+Once installed, you can verify the installation by running a simple feature extraction example:
+
+```python
+from interpreTS import FeatureExtractor
+import pandas as pd
+
+data = pd.DataFrame({'value': [1, 2, 3, 4, 5]})
+extractor = FeatureExtractor(features=['length'])
+features = extractor.extract_features(data)
+print("Extracted Features:", features)
+```
+
+For any issues, please consult our [Issue Tracker](https://github.com/ruleminer/InterpreTS/issues) on GitHub.
\ No newline at end of file
diff --git a/docs/README.md b/docs/README.md
new file mode 100644
index 0000000..f902968
--- /dev/null
+++ b/docs/README.md
@@ -0,0 +1,38 @@
+# InterpreTS
+
+Feature extraction from time series to support the creation of interpretable and explainable predictive models.
+
+## Overview
+InterpreTS is a Python library designed for extracting meaningful and interpretable features from time series data. With the growing importance of interpretability in machine learning and AI, InterpreTS focuses on creating feature representations that facilitate the development of interpretable and explainable predictive models.
+
+## Key Features
+- **Statistical Features**: Extract basic statistics like mean, standard deviation, minimum, and maximum values.
+- **Frequency Features**: Calculate features in the frequency domain, such as Fourier Transform coefficients.
+- **Relational Features**: Generate features describing relationships between different time series, such as correlation.
+- **Parallel Computing Support**: Efficiently compute features with parallel processing.
+- **Data Format Flexibility**: Easily convert and process data in `pandas.DataFrame` or `numpy.array` formats.
+
+## Requirements
+- Python 3.8 or above
+- pandas
+- numpy
+
+## Installation
+To install InterpreTS, follow the steps in [Installation Guide](docs/INSTALLATION.md).
+
+## Quickstart
+To begin using InterpreTS, see the [Usage Guide](docs/USAGE.md) or follow the example below:
+
+```python
+from interpreTS import FeatureExtractor, TimeSeriesData
+import pandas as pd
+
+# Sample data
+data = pd.DataFrame({'value': [1, 2, 3, 4, 5]})
+
+# Initialize the feature extractor with desired features
+extractor = FeatureExtractor(features=['length'])
+
+# Extract features
+features = extractor.extract_features(data)
+print("Extracted Features:", features)
diff --git a/docs/USAGE.md b/docs/USAGE.md
new file mode 100644
index 0000000..c6f00c7
--- /dev/null
+++ b/docs/USAGE.md
@@ -0,0 +1,23 @@
+# Usage Guide for InterpreTS
+
+This guide will walk you through using InterpreTS to extract features from time series data. Below are some examples demonstrating the primary functionalities of InterpreTS.
+
+## Basic Feature Extraction
+
+The following example demonstrates how to use FeatureExtractor to extract basic statistical and frequency-based features.
+
+```python
+from interpreTS import FeatureExtractor
+import pandas as pd
+
+# Sample time series data
+data = pd.DataFrame({'value': [1, 2, 3, 4, 5]})
+
+# Initialize the feature extractor with statistical and frequency features
+extractor = FeatureExtractor(features=['length'])
+
+# Extract features
+features = extractor.extract_features(data)
+print("Extracted Features:", features)
+
+```
\ No newline at end of file
diff --git a/examples/core/basic_usage.ipynb b/examples/core/basic_usage.ipynb
new file mode 100644
index 0000000..892c0a4
--- /dev/null
+++ b/examples/core/basic_usage.ipynb
@@ -0,0 +1,111 @@
+{
+ "cells": [
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Requirement already satisfied: pandas in c:\\users\\slawek\\appdata\\local\\programs\\python\\python39\\lib\\site-packages (1.2.0)\n",
+      "Requirement already satisfied: python-dateutil>=2.7.3 in c:\\users\\slawek\\appdata\\local\\programs\\python\\python39\\lib\\site-packages (from pandas) (2.9.0.post0)\n",
+      "Requirement already satisfied: pytz>=2017.3 in c:\\users\\slawek\\appdata\\local\\programs\\python\\python39\\lib\\site-packages (from pandas) (2024.1)\n",
+      "Requirement already satisfied: numpy>=1.16.5 in c:\\users\\slawek\\appdata\\local\\programs\\python\\python39\\lib\\site-packages (from pandas) (1.23.5)\n",
+      "Requirement already satisfied: six>=1.5 in c:\\users\\slawek\\appdata\\local\\programs\\python\\python39\\lib\\site-packages (from python-dateutil>=2.7.3->pandas) (1.16.0)\n",
+      "Note: you may need to restart the kernel to use updated packages.\n"
+     ]
+    },
+    {
+     "name": "stderr",
+     "output_type": "stream",
+     "text": [
+      "WARNING: Ignoring invalid distribution -atplotlib (c:\\users\\slawek\\appdata\\local\\programs\\python\\python39\\lib\\site-packages)\n",
+      "WARNING: Ignoring invalid distribution -atplotlib (c:\\users\\slawek\\appdata\\local\\programs\\python\\python39\\lib\\site-packages)\n",
+      "WARNING: Ignoring invalid distribution -atplotlib (c:\\users\\slawek\\appdata\\local\\programs\\python\\python39\\lib\\site-packages)\n"
+     ]
+    }
+   ],
+   "source": [
+    "pip install pandas # type: ignore"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 71,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Training Data:\n",
+      " 2023-01-01    1\n",
+      "2023-01-02    2\n",
+      "2023-01-03    3\n",
+      "2023-01-04    4\n",
+      "2023-01-05    5\n",
+      "2023-01-06    6\n",
+      "2023-01-07    7\n",
+      "Freq: D, dtype: int64\n",
+      "Test Data:\n",
+      " 2023-01-08     8\n",
+      "2023-01-09     9\n",
+      "2023-01-10    10\n",
+      "Freq: D, dtype: int64\n",
+      "\n",
+      "Extracted Features:\n",
+      "Length of the time series: 10\n"
+     ]
+    }
+   ],
+   "source": [
+    "import pandas as pd\n",
+    "import sys\n",
+    "import os\n",
+    "\n",
+    "# Adding path to src directory so notebook can import modules\n",
+    "sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname('__file__'), '../../src')))\n",
+    "from core.feature_extractor import FeatureExtractor\n",
+    "from src.utils.data_conversion import convert_to_time_series\n",
+    "from src.utils.data_validation import validate_time_series_data\n",
+    "\n",
+    "# Creating Sample Time Series Data\n",
+    "data = pd.Series([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], index=pd.date_range(\"2023-01-01\", periods=10))\n",
+    "\n",
+    "# Validating data before further processing\n",
+    "try:\n",
+    "    validate_time_series_data(data)\n",
+    "except (TypeError, ValueError) as e:\n",
+    "    print(f\"Validation error: {e}\")\n",
+    "    sys.exit(1)  # Stops execution if data is invalid\n",
+    "\n",
+    "# Converting data to TimeSeriesData object\n",
+    "ts_data = convert_to_time_series(data)\n",
+    "\n",
+    "# Splitting the data into training and test sets\n",
+    "train_data, test_data = ts_data.split(0.7)\n",
+    "print(\"Training Data:\\n\", train_data.data)\n",
+    "print(\"Test Data:\\n\", test_data.data)\n",
+    "\n",
+    "# Feature extractor initialization\n",
+    "extractor = FeatureExtractor(features=['length'])\n",
+    "\n",
+    "# Extracting features from data\n",
+    "features = extractor.extract_features(ts_data.data)\n",
+    "\n",
+    "# Displaying results\n",
+    "print(\"\\nExtracted Features:\")\n",
+    "print(\"Length of the time series:\", features['length'])\n"
+   ]
+  }
+ ],
+ "metadata": {
+  "language_info": {
+   "name": "python"
+  }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/examples/core/feature_extraction_example.ipynb b/examples/core/feature_extraction_example.ipynb
new file mode 100644
index 0000000..5a3a5e2
--- /dev/null
+++ b/examples/core/feature_extraction_example.ipynb
@@ -0,0 +1,127 @@
+{
+ "cells": [
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Requirement already satisfied: pandas in c:\\users\\slawek\\appdata\\local\\programs\\python\\python39\\lib\\site-packages (1.2.0)\n",
+      "Requirement already satisfied: python-dateutil>=2.7.3 in c:\\users\\slawek\\appdata\\local\\programs\\python\\python39\\lib\\site-packages (from pandas) (2.9.0.post0)\n",
+      "Requirement already satisfied: pytz>=2017.3 in c:\\users\\slawek\\appdata\\local\\programs\\python\\python39\\lib\\site-packages (from pandas) (2024.1)\n",
+      "Requirement already satisfied: numpy>=1.16.5 in c:\\users\\slawek\\appdata\\local\\programs\\python\\python39\\lib\\site-packages (from pandas) (1.23.5)\n",
+      "Requirement already satisfied: six>=1.5 in c:\\users\\slawek\\appdata\\local\\programs\\python\\python39\\lib\\site-packages (from python-dateutil>=2.7.3->pandas) (1.16.0)\n",
+      "Note: you may need to restart the kernel to use updated packages.\n"
+     ]
+    },
+    {
+     "name": "stderr",
+     "output_type": "stream",
+     "text": [
+      "WARNING: Ignoring invalid distribution -atplotlib (c:\\users\\slawek\\appdata\\local\\programs\\python\\python39\\lib\\site-packages)\n",
+      "WARNING: Ignoring invalid distribution -atplotlib (c:\\users\\slawek\\appdata\\local\\programs\\python\\python39\\lib\\site-packages)\n",
+      "WARNING: Ignoring invalid distribution -atplotlib (c:\\users\\slawek\\appdata\\local\\programs\\python\\python39\\lib\\site-packages)\n"
+     ]
+    }
+   ],
+   "source": [
+    "pip install pandas # type: ignore"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 2,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Resampled Data:\n",
+      " 2023-01-01    4.0\n",
+      "2023-01-03    4.0\n",
+      "2023-01-05    5.5\n",
+      "2023-01-07    5.5\n",
+      "2023-01-09    5.0\n",
+      "Freq: 2D, dtype: float64\n",
+      "\n",
+      "Features from Original Data:\n",
+      "{'length': 10}\n",
+      "\n",
+      "Features from Resampled Data:\n",
+      "{'length': 5}\n"
+     ]
+    },
+    {
+     "name": "stderr",
+     "output_type": "stream",
+     "text": [
+      "c:\\Users\\slawek\\Desktop\\Praca naukowa\\InterpreTS\\src\\core\\time_series_data.py:53: FutureWarning: Index.is_all_dates is deprecated, will be removed in a future version.  check index.inferred_type instead\n",
+      "  if isinstance(self.data, pd.Series) and self.data.index.is_all_dates:\n"
+     ]
+    }
+   ],
+   "source": [
+    "# Importy\n",
+    "import pandas as pd\n",
+    "import sys\n",
+    "import os\n",
+    "\n",
+    "# Adding path to src directory so notebook can import modules\n",
+    "sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname('__file__'), '../../src')))\n",
+    "from core.time_series_data import TimeSeriesData\n",
+    "from core.feature_extractor import FeatureExtractor\n",
+    "\n",
+    "# Creating sample time data with time index\n",
+    "data_with_date = pd.Series(\n",
+    "    [5, 3, 6, 2, 7, 4, 8, 3, 9, 1],\n",
+    "    index=pd.date_range(\"2023-01-01\", periods=10, freq=\"D\")\n",
+    ")\n",
+    "\n",
+    "# TimeSeriesData object initialization\n",
+    "ts_data = TimeSeriesData(data_with_date)\n",
+    "\n",
+    "# Resampling data to a two-day interval\n",
+    "resampled_ts_data = ts_data.resample(\"2D\")\n",
+    "print(\"Resampled Data:\\n\", resampled_ts_data.data)\n",
+    "\n",
+    "# Extraction of several features from the original data\n",
+    "extractor = FeatureExtractor(features=['length'])  # Możesz dodać więcej cech w przyszłości\n",
+    "\n",
+    "# Invoking the feature extractor on the original data\n",
+    "features_original = extractor.extract_features(ts_data.data)\n",
+    "print(\"\\nFeatures from Original Data:\")\n",
+    "print(features_original)\n",
+    "\n",
+    "# Calling the feature extractor on the resampled data\n",
+    "features_resampled = extractor.extract_features(resampled_ts_data.data)\n",
+    "print(\"\\nFeatures from Resampled Data:\")\n",
+    "print(features_resampled)\n"
+   ]
+  }
+ ],
+ "metadata": {
+  "kernelspec": {
+   "display_name": "Python 3",
+   "language": "python",
+   "name": "python3"
+  },
+  "language_info": {
+   "codemirror_mode": {
+    "name": "ipython",
+    "version": 3
+   },
+   "file_extension": ".py",
+   "mimetype": "text/x-python",
+   "name": "python",
+   "nbconvert_exporter": "python",
+   "pygments_lexer": "ipython3",
+   "version": "3.9.13"
+  }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/examples/core/features/feature_length.ipynb b/examples/core/features/feature_length.ipynb
new file mode 100644
index 0000000..773ef0f
--- /dev/null
+++ b/examples/core/features/feature_length.ipynb
@@ -0,0 +1,80 @@
+{
+ "cells": [
+  {
+   "cell_type": "code",
+   "execution_count": null,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Note: you may need to restart the kernel to use updated packages.\n"
+     ]
+    },
+    {
+     "name": "stderr",
+     "output_type": "stream",
+     "text": [
+      "ERROR: Invalid requirement: '#': Expected package name at the start of dependency specifier\n",
+      "    #\n",
+      "    ^\n"
+     ]
+    }
+   ],
+   "source": [
+    "pip install pandas # type: ignore"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 44,
+   "metadata": {},
+   "outputs": [
+    {
+     "name": "stdout",
+     "output_type": "stream",
+     "text": [
+      "Length Feature: 6\n"
+     ]
+    }
+   ],
+   "source": [
+    "import pandas as pd\n",
+    "import sys\n",
+    "import os\n",
+    "\n",
+    "# Adding path to src directory so notebook can import modules\n",
+    "sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname('__file__'), '../../../src')))\n",
+    "from core.time_series_data import TimeSeriesData\n",
+    "from core.feature_extractor import FeatureExtractor\n",
+    "\n",
+    "# Data preparation\n",
+    "data = pd.Series([1, 2, 3, 4, 5, 6])\n",
+    "\n",
+    "# Initialization TimeSeriesData\n",
+    "ts_data = TimeSeriesData(data)\n",
+    "\n",
+    "\n",
+    "# Splitting the data into training and test sets\n",
+    "train_data, test_data = ts_data.split(0.6)\n",
+    "\n",
+    "# Feature extractor initialization\n",
+    "extractor = FeatureExtractor(features=['length'])\n",
+    "\n",
+    "# Extracting features from data\n",
+    "features = extractor.extract_features(data)\n",
+    "\n",
+    "# Displaying results\n",
+    "print(\"Length Feature:\", features['length'])"
+   ]
+  }
+ ],
+ "metadata": {
+  "language_info": {
+   "name": "python"
+  }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000..03adf8e
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1,3 @@
+pandas
+numpy
+sktime
\ No newline at end of file
diff --git a/setup.py b/setup.py
new file mode 100644
index 0000000..f33c243
--- /dev/null
+++ b/setup.py
@@ -0,0 +1,29 @@
+from setuptools import setup, find_packages
+
+setup(
+    name="InterpreTS",
+    version="0.1.0",
+    packages=find_packages(),
+    install_requires=[
+        "pandas>=1.0.0",
+        "numpy>=1.18.0"
+    ],
+    description="Feature extraction from time series to support the creation of interpretable and explainable predictive models.",
+    long_description=open("docs/README.md").read(),
+    long_description_content_type="text/markdown",
+    author="Your Name",
+    author_email="your.email@example.com",
+    url="https://github.com/ruleminer/InterpreTS",
+    classifiers=[
+        "Programming Language :: Python :: 3",
+        "License :: OSI Approved :: MIT License",
+        "Operating System :: OS Independent",
+    ],
+    python_requires=">=3.8",
+    keywords="time series feature extraction interpretability explainability machine learning",
+    project_urls={
+        "Documentation": "https://github.com/ruleminer/InterpreTS/docs",
+        "Source": "https://github.com/ruleminer/InterpreTS",
+        "Tracker": "https://github.com/ruleminer/InterpreTS/issues",
+    },
+)
diff --git a/src/__init__.py b/src/__init__.py
new file mode 100644
index 0000000..88da7a2
--- /dev/null
+++ b/src/__init__.py
@@ -0,0 +1,4 @@
+from .core.feature_extractor import FeatureExtractor
+from .core.time_series_data import TimeSeriesData
+from .utils.data_conversion import convert_to_time_series
+from .utils.data_validation import validate_time_series_data
\ No newline at end of file
diff --git a/src/core/__init__.py b/src/core/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/src/core/feature_extractor.py b/src/core/feature_extractor.py
new file mode 100644
index 0000000..4a4776b
--- /dev/null
+++ b/src/core/feature_extractor.py
@@ -0,0 +1,50 @@
+from .features.feature_length import calculate_feature_length
+
+class FeatureExtractor:
+    """
+    A class to manage and execute feature extraction on time series data.
+    """
+
+    def __init__(self, features=None):
+        """
+        Initialize the FeatureExtractor with a list of features to calculate.
+        
+        Parameters
+        ----------
+        features : list of str, optional
+            A list of features to calculate. Default is None, which calculates all available features.
+        """
+        
+        
+        self.features = features if features is not None else ['length']
+
+    def extract_features(self, data):
+        """
+        Extract features from a time series dataset.
+        
+        Parameters
+        ----------
+        data : pd.Series or np.ndarray
+            The time series data for which features are to be extracted.
+            
+        Returns
+        -------
+        dict
+            A dictionary containing calculated features and their values.
+            
+        Examples
+        --------
+        >>> import pandas as pd
+        >>> data = pd.Series([1, 2, 3, 4, 5])
+        >>> extractor = FeatureExtractor(features=['length'])
+        >>> extractor.extract_features(data)
+        {'length': 5}
+        """
+        
+        
+        extracted_features = {}
+        
+        if 'length' in self.features:
+            extracted_features['length'] = calculate_feature_length(data)
+                
+        return extracted_features
diff --git a/src/core/features/__init__.py b/src/core/features/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/src/core/features/feature_length.py b/src/core/features/feature_length.py
new file mode 100644
index 0000000..257560f
--- /dev/null
+++ b/src/core/features/feature_length.py
@@ -0,0 +1,33 @@
+from sktime.utils.validation.series import check_series
+
+def calculate_feature_length(data):
+    """
+    Calculate the number of data points in a time series.
+
+    Parameters
+    ----------
+    data : pd.Series or np.ndarray
+        The time series data for which the length feature is to be calculated.
+        
+    Returns
+    -------
+    int
+        The number of data points in the provided time series.
+        
+    Examples
+    --------
+    >>> import pandas as pd
+    >>> data = pd.Series([1, 2, 3, 4, 5])
+    >>> calculate_length(data)
+    5
+    """
+    
+    
+    # Check if the data is empty
+    if len(data) == 0:
+        return 0
+    
+    # Validate the time series using sktime's validation tools
+    data = check_series(data)
+    
+    return len(data)
diff --git a/src/core/time_series_data.py b/src/core/time_series_data.py
new file mode 100644
index 0000000..53d26e3
--- /dev/null
+++ b/src/core/time_series_data.py
@@ -0,0 +1,86 @@
+import pandas as pd
+
+class TimeSeriesData:
+    """
+    A class to manage and process time series data.
+    """
+
+    def __init__(self, data):
+        """
+        Initialize the TimeSeriesData with time series data.
+        
+        Parameters
+        ----------
+        data : pd.Series, pd.DataFrame, or np.ndarray
+            The time series data to be managed. If provided as a numpy array,
+            it will be converted to a pandas DataFrame for consistency.
+            
+        Examples
+        --------
+        >>> import pandas as pd
+        >>> data = pd.Series([1, 2, 3, 4, 5])
+        >>> ts_data = TimeSeriesData(data)
+        """
+        
+        
+        if isinstance(data, (pd.Series, pd.DataFrame)):
+            self.data = data
+        else:
+            raise ValueError("Data must be a pandas Series or DataFrame.")
+    
+    def resample(self, interval):
+        """
+        Resample the time series data to a specified interval.
+        
+        Parameters
+        ----------
+        interval : str
+            The interval to resample the data, e.g., 'D' for daily, 'H' for hourly.
+            
+        Returns
+        -------
+        TimeSeriesData
+            A new TimeSeriesData object with resampled data.
+            
+        Examples
+        --------
+        >>> data = pd.Series([1, 2, 3, 4, 5], index=pd.date_range("2023-01-01", periods=5, freq="D"))
+        >>> ts_data = TimeSeriesData(data)
+        >>> resampled_data = ts_data.resample("2D")
+        """
+        
+        
+        if isinstance(self.data, pd.Series) and self.data.index.is_all_dates:
+            resampled_data = self.data.resample(interval).mean()
+        else:
+            raise ValueError("Data must have a DateTime index for resampling.")
+        
+        return TimeSeriesData(resampled_data)
+
+    def split(self, train_size=0.7):
+        """
+        Split the time series data into training and test sets.
+        
+        Parameters
+        ----------
+        train_size : float, optional
+            The proportion of the data to use for training, by default 0.7.
+            
+        Returns
+        -------
+        tuple of TimeSeriesData
+            A tuple containing the training and test sets as TimeSeriesData objects.
+            
+        Examples
+        --------
+        >>> data = pd.Series([1, 2, 3, 4, 5])
+        >>> ts_data = TimeSeriesData(data)
+        >>> train, test = ts_data.split(0.6)
+        """
+        
+        
+        split_index = int(len(self.data) * train_size)
+        train_data = self.data[:split_index]
+        test_data = self.data[split_index:]
+        
+        return TimeSeriesData(train_data), TimeSeriesData(test_data)
diff --git a/src/utils/__init__.py b/src/utils/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/src/utils/data_conversion.py b/src/utils/data_conversion.py
new file mode 100644
index 0000000..940d6ff
--- /dev/null
+++ b/src/utils/data_conversion.py
@@ -0,0 +1,37 @@
+import pandas as pd
+import numpy as np
+from ..core.time_series_data import TimeSeriesData
+
+def convert_to_time_series(data):
+    """
+    Convert input data to a TimeSeriesData object.
+    
+    Parameters
+    ----------
+    data : pd.DataFrame, pd.Series, or np.ndarray
+        The data to be converted into a TimeSeriesData object.
+        
+    Returns
+    -------
+    TimeSeriesData
+        An instance of TimeSeriesData wrapping the input data.
+        
+    Raises
+    ------
+    TypeError
+        If the input data is not of type pd.DataFrame, pd.Series, or np.ndarray.
+        
+    Examples
+    --------
+    >>> import pandas as pd
+    >>> data = pd.Series([1, 2, 3, 4, 5])
+    >>> ts_data = convert_to_time_series(data)
+    """
+    
+    
+    if isinstance(data, (pd.DataFrame, pd.Series)):
+        return TimeSeriesData(data)
+    elif isinstance(data, np.ndarray):
+        return TimeSeriesData(pd.Series(data))
+    else:
+        raise TypeError("Data must be of type pandas DataFrame, Series, or numpy array.")
diff --git a/src/utils/data_validation.py b/src/utils/data_validation.py
new file mode 100644
index 0000000..7c9e278
--- /dev/null
+++ b/src/utils/data_validation.py
@@ -0,0 +1,47 @@
+import pandas as pd
+import numpy as np
+
+def validate_time_series_data(data):
+    """
+    Validate if the input data is suitable for time series processing.
+    
+    Parameters
+    ----------
+    data : pd.Series, pd.DataFrame, or np.ndarray
+        The time series data to be validated.
+        
+    Returns
+    -------
+    bool
+        True if the data is valid; raises an error otherwise.
+        
+    Raises
+    ------
+    TypeError
+        If data is not a pd.Series, pd.DataFrame, or np.ndarray.
+    ValueError
+        If the data contains NaN values or if pd.Series/pd.DataFrame has no DateTime index.
+        
+    Examples
+    --------
+    >>> import pandas as pd
+    >>> data = pd.Series([1, 2, 3, 4, 5])
+    >>> validate_time_series_data(data)
+    True
+    """
+    
+    
+    if not isinstance(data, (pd.Series, pd.DataFrame, np.ndarray)):
+        raise TypeError("Data must be a pandas Series, DataFrame, or numpy array.")
+    
+    if isinstance(data, (pd.Series, pd.DataFrame)):
+        if data.isnull().any().any():
+            raise ValueError("Data contains NaN values.")
+        if isinstance(data, pd.Series) and data.index.is_all_dates:
+            pass
+        elif isinstance(data, pd.DataFrame) and isinstance(data.index, pd.DatetimeIndex):
+            pass
+        else:
+            raise ValueError("DataFrame or Series must have a DateTime index for time-based operations.")
+    
+    return True


Test patch:
diff --git a/tests/__init__.py b/tests/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/tests/core/__init__.py b/tests/core/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/tests/core/features/__init__.py b/tests/core/features/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/tests/core/features/test_feature_length.py b/tests/core/features/test_feature_length.py
new file mode 100644
index 0000000..22eee60
--- /dev/null
+++ b/tests/core/features/test_feature_length.py
@@ -0,0 +1,33 @@
+import pytest
+import pandas as pd
+from src.core.features.feature_length import calculate_feature_length
+
+def test_calculate_length():
+    """
+    Test the calculate_length function to ensure it correctly calculates
+    the number of data points in a time series.
+    """
+    # Przykład danych
+    data = pd.Series([1, 2, 3, 4, 5])
+
+    # Sprawdzenie poprawności wyniku
+    assert calculate_feature_length(data) == 5, "The length of the time series should be 5"
+
+def test_calculate_length_empty_series():
+    """
+    Test the calculate_length function with an empty time series.
+    """
+    data = pd.Series([])
+
+    # Sprawdzenie poprawności wyniku dla pustego szeregu
+    assert calculate_feature_length(data) == 0, "The length of an empty time series should be 0"
+
+def test_calculate_length_array():
+    """
+    Test the calculate_length function with a numpy array.
+    """
+    import numpy as np
+    data = np.array([1, 2, 3, 4, 5])
+
+    # Sprawdzenie poprawności wyniku dla numpy array
+    assert calculate_feature_length(data) == 5, "The length of the numpy array time series should be 5"
diff --git a/tests/core/test_feature_extractor.py b/tests/core/test_feature_extractor.py
new file mode 100644
index 0000000..b8d63d5
--- /dev/null
+++ b/tests/core/test_feature_extractor.py
@@ -0,0 +1,21 @@
+import pytest
+import pandas as pd
+from src.core.feature_extractor import FeatureExtractor
+
+def test_extract_length_feature():
+    """
+    Test that FeatureExtractor correctly extracts the 'length' feature.
+    """
+    data = pd.Series([1, 2, 3, 4, 5])
+    extractor = FeatureExtractor(features=['length'])
+    features = extractor.extract_features(data)
+    assert features['length'] == 5, "The 'length' feature should be 5"
+
+def test_extract_no_features():
+    """
+    Test that FeatureExtractor returns an empty dictionary when no features are specified.
+    """
+    data = pd.Series([1, 2, 3, 4, 5])
+    extractor = FeatureExtractor(features=[])
+    features = extractor.extract_features(data)
+    assert features == {}, "No features should be extracted when an empty feature list is provided"
diff --git a/tests/core/test_time_series_data.py b/tests/core/test_time_series_data.py
new file mode 100644
index 0000000..0f6f480
--- /dev/null
+++ b/tests/core/test_time_series_data.py
@@ -0,0 +1,30 @@
+import pytest
+import pandas as pd
+from src.core.time_series_data import TimeSeriesData
+
+def test_time_series_initialization():
+    """
+    Test the initialization of TimeSeriesData with a pandas Series.
+    """
+    data = pd.Series([1, 2, 3, 4, 5])
+    ts_data = TimeSeriesData(data)
+    assert ts_data.data.equals(data), "The data should be initialized correctly"
+
+def test_time_series_resample():
+    """
+    Test the resampling of TimeSeriesData with a datetime index.
+    """
+    data = pd.Series([1, 2, 3, 4, 5], index=pd.date_range("2023-01-01", periods=5, freq="D"))
+    ts_data = TimeSeriesData(data)
+    resampled_data = ts_data.resample("2D")
+    assert len(resampled_data.data) == 3, "The resampled data should have 3 points for 2-day frequency"
+
+def test_time_series_split():
+    """
+    Test the split functionality of TimeSeriesData.
+    """
+    data = pd.Series([1, 2, 3, 4, 5])
+    ts_data = TimeSeriesData(data)
+    train_data, test_data = ts_data.split(0.6)
+    assert len(train_data.data) == 3, "The training set should have 60% of the data"
+    assert len(test_data.data) == 2, "The test set should have 40% of the data"
diff --git a/tests/utils/__init__.py b/tests/utils/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/tests/utils/test_convert_to_time_series.py b/tests/utils/test_convert_to_time_series.py
new file mode 100644
index 0000000..7da0623
--- /dev/null
+++ b/tests/utils/test_convert_to_time_series.py
@@ -0,0 +1,30 @@
+import pytest
+import pandas as pd
+import numpy as np
+from src.utils.data_conversion import convert_to_time_series
+from src.core.time_series_data import TimeSeriesData
+
+def test_convert_pandas_series():
+    """
+    Test conversion of pandas Series to TimeSeriesData.
+    """
+    data = pd.Series([1, 2, 3, 4, 5])
+    ts_data = convert_to_time_series(data)
+    assert isinstance(ts_data, TimeSeriesData), "The result should be an instance of TimeSeriesData"
+    assert ts_data.data.equals(data), "The data should match the original pandas Series"
+
+def test_convert_numpy_array():
+    """
+    Test conversion of numpy array to TimeSeriesData.
+    """
+    data = np.array([1, 2, 3, 4, 5])
+    ts_data = convert_to_time_series(data)
+    assert isinstance(ts_data, TimeSeriesData), "The result should be an instance of TimeSeriesData"
+    assert ts_data.data.equals(pd.Series(data)), "The data should match the converted pandas Series"
+
+def test_convert_invalid_type():
+    """
+    Test that convert_to_time_series raises an error with invalid data types.
+    """
+    with pytest.raises(TypeError):
+        convert_to_time_series("invalid data")
diff --git a/tests/utils/test_validate_time_series_data.py b/tests/utils/test_validate_time_series_data.py
new file mode 100644
index 0000000..2b54e9d
--- /dev/null
+++ b/tests/utils/test_validate_time_series_data.py
@@ -0,0 +1,42 @@
+import pytest
+import pandas as pd
+import numpy as np
+from src.utils.data_validation import validate_time_series_data
+
+def test_validate_pandas_series():
+    """
+    Test validation of a valid pandas Series.
+    """
+    data = pd.Series([1, 2, 3, 4, 5], index=pd.date_range("2023-01-01", periods=5))
+    assert validate_time_series_data(data) == True, "The validation should pass for a valid pandas Series"
+
+def test_validate_with_nan_values():
+    """
+    Test that validation raises an error for data containing NaN values.
+    """
+    data = pd.Series([1, np.nan, 3, 4, 5], index=pd.date_range("2023-01-01", periods=5))
+    with pytest.raises(ValueError):
+        validate_time_series_data(data)
+
+def test_validate_without_datetime_index():
+    """
+    Test that validation raises an error for a Series without DateTime index.
+    """
+    data = pd.Series([1, 2, 3, 4, 5])
+    with pytest.raises(ValueError):
+        validate_time_series_data(data)
+
+def test_validate_numpy_array():
+    """
+    Test validation of a valid numpy array.
+    """
+    data = np.array([1, 2, 3, 4, 5])
+    assert validate_time_series_data(data) == True, "The validation should pass for a valid numpy array"
+
+def test_validate_invalid_type():
+    """
+    Test that validation raises an error for an invalid data type.
+    """
+    data = "invalid data"
+    with pytest.raises(TypeError):
+        validate_time_series_data(data)