## `eigenkit.datasets`

The datasets of eigenkit: the registry of their metadata, and the loaders.

### `FONTSIZE_AXES = 20`

The font size, in points, that `rc_params()` gives the axis labels and titles.

### `FONTSIZE_LEGEND = 18`

The font size, in points, that `rc_params()` gives the legend entries.

### `FONTSIZE_TICKS = 16`

The font size, in points, of the tick labels, which is also the base `font.size`.

### `STYLE_COLORS = ('#CE2173', '#AA5EFF', '#7D4ECF', '#43CDFF', '#3333FB', '#11E57A', '#E6C541', '#94A3B8')`

The plot palette of the library, in the order of the colour cycle.

`rc_params()` sets it as `axes.prop_cycle`, so a plot drawn inside that context uses these colours without naming them. Index it when a series needs a fixed colour, and not the next one in the cycle. For example, use `STYLE_COLORS[0]` for a training curve and `STYLE_COLORS[1]` for validation, so that the two curves keep their colours across figures. It is a tuple, so that an `append` by mistake cannot change how every later plot in the process looks.

### `DatasetInfo`

Bases: `BaseModel`

The metadata of a dataset that eigenkit provides.

Parameters:

| Name                  | Type        | Description                                                                                                                                                                                                                                                      | Default    |
| --------------------- | ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
| `name`                | `str`       | The unique name of the dataset, which is also its key in REGISTRY.                                                                                                                                                                                               | *required* |
| `source`              | `str`       | Where the dataset comes from. It is one of these values: 'sklearn': the dataset is loaded with a function of sklearn.datasets. 'url': the dataset is downloaded from a web address. 'synthetic': the dataset is generated by a function, for example make_moons. | *required* |
| `url`                 | `str`       | The web address of the file to download. It is used only when source='url'.                                                                                                                                                                                      | `None`     |
| `sha256`              | `str`       | The SHA-256 hash, in hexadecimal, that the downloaded file must match. A downloaded file that does not match is deleted, and a ValueError is raised. A cached file that does not match is downloaded again. It is used only when source='url'.                   | `None`     |
| `sklearn_loader`      | `str`       | The name of the sklearn.datasets function, for example 'load_iris'. It is used only when source='sklearn'.                                                                                                                                                       | `None`     |
| `synthetic_generator` | `str`       | The name of the generator function, for example 'make_moons'. It is used only when source='synthetic'.                                                                                                                                                           | `None`     |
| `task`                | `str`       | The type of task: 'classification', 'regression', 'timeseries', 'optimization' or 'chemistry'.                                                                                                                                                                   | *required* |
| `n_features`          | `int`       | The number of input features. It must be at least 1.                                                                                                                                                                                                             | *required* |
| `n_samples`           | `int`       | The total number of samples. It is None when the number is not recorded, for example for the synthetic datasets, whose size is chosen when they are generated.                                                                                                   | `None`     |
| `n_classes`           | `int`       | The number of classes. It is None for regression and time-series tasks.                                                                                                                                                                                          | `None`     |
| `feature_names`       | `list[str]` | Readable names of the input features.                                                                                                                                                                                                                            | `None`     |
| `target_names`        | `list[str]` | Readable names of the classes, or of the output.                                                                                                                                                                                                                 | `None`     |
| `window_size`         | `int`       | The recommended size of the sliding window, for time-series datasets.                                                                                                                                                                                            | `None`     |
| `description`         | `str`       | A short description of the dataset.                                                                                                                                                                                                                              | *required* |

Example

```python
info = DatasetInfo(
    name="iris",
    source="sklearn",
    sklearn_loader="load_iris",
    task="classification",
    n_features=4,
    n_samples=150,
    n_classes=3,
    description="Classic multi-class classification dataset.",
)
```

### `DatasetReport`

An exploratory data analysis (EDA) report for a built-in or custom dataset.

Parameters:

| Name            | Type        | Description                                                                                    | Default    |
| --------------- | ----------- | ---------------------------------------------------------------------------------------------- | ---------- |
| `X`             | `ndarray`   | The feature matrix, of shape (n_samples, n_features).                                          | *required* |
| `y`             | `ndarray`   | The target vector, of shape (n_samples,).                                                      | *required* |
| `feature_names` | `list[str]` | Readable names of the features, in the order of the columns of X.                              | *required* |
| `target_name`   | `str`       | The name of the target in the plots and the summary.                                           | *required* |
| `task`          | `str`       | The type of task, usually "classification", "regression" or "timeseries".                      | *required* |
| `metadata`      | `Any`       | The metadata of the dataset, for example a DatasetInfo.                                        | `None`     |
| `time_index`    | `Any`       | The time axis for the time-series plots. It can be numeric (array-like) or a pd.DatetimeIndex. | `None`     |
| `theme`         | `str`       | The theme of the plots, "light" or "dark".                                                     | `'light'`  |

Notes

The recommended way to build a report is `from_data()`, which accepts the dictionaries returned by `load_dataset(...)` as well as your own `X` and `y`.

Example

```python
from eigenkit.datasets import DatasetReport, load_dataset

data = load_dataset("iris", split=False)
report = DatasetReport.from_data(data)
figs = report.plot_overview()
summary = report.summarize()
```

#### `from_data(data=None, *, X=None, y=None, feature_names=None, target_name='target', task=None, time_index=None, theme='light')`

Build a report from a dataset dictionary, or from your own arrays or tensors.

Parameters:

| Name            | Type             | Description                                                                                                                                               | Default    |
| --------------- | ---------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |
| `data`          | `dict[str, Any]` | A dataset dictionary in the format of eigenkit, either {"X", "y"} or {"X_train", "y_train", "X_test", "y_test"}. The training and test sets are combined. | `None`     |
| `X`             | `Any`            | Your own feature matrix, as a NumPy array, a pandas object, a PyTorch tensor or another array-like.                                                       | `None`     |
| `y`             | `Any`            | Your own target vector, in the same formats as X.                                                                                                         | `None`     |
| `feature_names` | `list[str]`      | The names of the features. If they are not given, the names come from the metadata, or they are feature_0, feature_1 and so on.                           | `None`     |
| `target_name`   | `str`            | The name of the target in the plots and the summary.                                                                                                      | `'target'` |
| `task`          | `str`            | The type of task. If it is not given, it is taken from the metadata, or guessed from y.                                                                   | `None`     |
| `time_index`    | `Any`            | The time axis for the time-series analysis.                                                                                                               | `None`     |
| `theme`         | `str`            | The theme of the plots, "light" or "dark".                                                                                                                | `'light'`  |

Returns:

| Type              | Description                                         |
| ----------------- | --------------------------------------------------- |
| `'DatasetReport'` | The report, ready for plotting and for the summary. |

Raises:

| Type         | Description                                                                                                                                |
| ------------ | ------------------------------------------------------------------------------------------------------------------------------------------ |
| `ValueError` | If the inputs are missing or do not agree, for example if the shapes do not match, or if feature_names does not have one name per feature. |

#### `plot(kind, **kwargs)`

Build one plot, chosen by its kind.

Parameters:

| Name       | Type  | Description                                                                                                         | Default    |
| ---------- | ----- | ------------------------------------------------------------------------------------------------------------------- | ---------- |
| `kind`     | `str` | The kind of plot: "data_health", "target", "distributions", "correlation", "feature_target" or "timeseries_target". | *required* |
| `**kwargs` | `Any` | Options of the plot, such as bins, max_features and max_points.                                                     | `{}`       |

Returns:

| Type  | Description            |
| ----- | ---------------------- |
| `Any` | The matplotlib figure. |

Raises:

| Type         | Description                            |
| ------------ | -------------------------------------- |
| `ValueError` | If kind is not one of the kinds above. |

#### `plot_overview(*, max_features=None, bins=30, max_points=2000, path=None)`

Build the default set of plots of the exploratory data analysis.

Parameters:

| Name           | Type  | Description                                                                                  | Default                                                                                           |
| -------------- | ----- | -------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- |
| `max_features` | `int` | The largest number of features shown in the panels about features. None shows every feature. | `None`                                                                                            |
| `bins`         | `int` | The number of histogram bins in the distribution plots.                                      | `30`                                                                                              |
| `max_points`   | `int` | The largest number of points in the scatter plots. Larger datasets are subsampled.           | `2000`                                                                                            |
| `path`         | \`str | Path\`                                                                                       | A directory where every overview plot is saved as a PNG file. With None, the plots are not saved. |

Returns:

| Type             | Description                                                                                                                         |
| ---------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| `dict[str, Any]` | A dictionary from each kind of plot to its matplotlib figure. The "timeseries_target" plot is included only for a time-series task. |

#### `summarize()`

Build a reproducible summary of the dataset, with recommendations.

Returns:

| Type             | Description                                                                                                                                                             |
| ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `dict[str, Any]` | A dictionary with statistics about the shape and the quality of the data, signals specific to the task when there are any, and a readable summary under the "text" key. |

### `generate_ad_hoc(n_samples=200, n_qubits=2, gap=0.3, random_state=42)`

Generate the "ad hoc" dataset of Havlíček et al., Nature 567, 209 (2019).

The dataset is designed so that a quantum kernel separates it. Each point `x` in `[0, 2π)^n` is encoded with the ZZ feature map, with two repetitions as in Qiskit's `ZZFeatureMap`. Its label is the sign of `⟨ψ(x)| V† Z^{⊗n} V |ψ(x)⟩` for a fixed random unitary `V`. The points closer than `gap` to the decision boundary are dropped, and the two classes are balanced. A kernel built from the same ZZ feature map classifies the data almost perfectly, and classical kernels usually do not.

Parameters:

| Name           | Type    | Description                                                                                        | Default                                              |
| -------------- | ------- | -------------------------------------------------------------------------------------------------- | ---------------------------------------------------- |
| `n_samples`    | `int`   | The number of points, split evenly between the two classes.                                        | `200`                                                |
| `n_qubits`     | `int`   | The number of features, which is also the number of qubits of the circuit that generates the data. | `2`                                                  |
| `gap`          | `float` | The margin around the decision boundary, in \[0, 1).                                               | `0.3`                                                |
| `random_state` | \`int   | None\`                                                                                             | The seed of the unitary V and of the sampled points. |

Returns:

| Type                      | Description                                                                                                 |
| ------------------------- | ----------------------------------------------------------------------------------------------------------- |
| `tuple[ndarray, ndarray]` | The pair (X, y), with X of shape (n_samples, n_qubits) and y of shape (n_samples,). The labels are 0 and 1. |

Raises:

| Type         | Description                                   |
| ------------ | --------------------------------------------- |
| `ValueError` | If gap is not in \[0, 1), or if n_qubits < 1. |

### `generate_checkerboard(n_samples=200, grid_size=2, random_state=42)`

Generate a dataset with a checkerboard pattern.

The points are drawn uniformly in `[0, grid_size]²`. The label is `(floor(x) + floor(y)) % 2`, which gives regions of alternating classes.

Parameters:

| Name           | Type  | Description                          | Default                                    |
| -------------- | ----- | ------------------------------------ | ------------------------------------------ |
| `n_samples`    | `int` | The number of points to generate.    | `200`                                      |
| `grid_size`    | `int` | The number of cells along each axis. | `2`                                        |
| `random_state` | \`int | None\`                               | The random seed, for reproducible results. |

Returns:

| Type                      | Description                                                                  |
| ------------------------- | ---------------------------------------------------------------------------- |
| `tuple[ndarray, ndarray]` | The pair (X, y), with X of shape (n_samples, 2) and y of shape (n_samples,). |

### `generate_circles(n_samples=200, noise=0.05, factor=0.5, random_state=42)`

Generate two concentric circles.

Parameters:

| Name           | Type    | Description                                                         | Default                                    |
| -------------- | ------- | ------------------------------------------------------------------- | ------------------------------------------ |
| `n_samples`    | `int`   | The number of points to generate.                                   | `200`                                      |
| `noise`        | `float` | The standard deviation of the Gaussian noise added to the data.     | `0.05`                                     |
| `factor`       | `float` | The ratio of the inner circle to the outer circle, between 0 and 1. | `0.5`                                      |
| `random_state` | \`int   | None\`                                                              | The random seed, for reproducible results. |

Returns:

| Type                      | Description                                                                  |
| ------------------------- | ---------------------------------------------------------------------------- |
| `tuple[ndarray, ndarray]` | The pair (X, y), with X of shape (n_samples, 2) and y of shape (n_samples,). |

### `generate_moons(n_samples=200, noise=0.1, random_state=42)`

Generate two half-circles that interleave, called moons.

Parameters:

| Name           | Type    | Description                                                     | Default                                    |
| -------------- | ------- | --------------------------------------------------------------- | ------------------------------------------ |
| `n_samples`    | `int`   | The number of points to generate.                               | `200`                                      |
| `noise`        | `float` | The standard deviation of the Gaussian noise added to the data. | `0.1`                                      |
| `random_state` | \`int   | None\`                                                          | The random seed, for reproducible results. |

Returns:

| Type                      | Description                                                                  |
| ------------------------- | ---------------------------------------------------------------------------- |
| `tuple[ndarray, ndarray]` | The pair (X, y), with X of shape (n_samples, 2) and y of shape (n_samples,). |

### `generate_regression(n_samples=200, n_features=4, noise=0.1, random_state=42)`

Generate a synthetic regression dataset with scikit-learn's `make_regression`.

Parameters:

| Name           | Type    | Description                                                 | Default                                    |
| -------------- | ------- | ----------------------------------------------------------- | ------------------------------------------ |
| `n_samples`    | `int`   | The number of samples to generate.                          | `200`                                      |
| `n_features`   | `int`   | The number of input features.                               | `4`                                        |
| `noise`        | `float` | The standard deviation of the Gaussian noise on the output. | `0.1`                                      |
| `random_state` | \`int   | None\`                                                      | The random seed, for reproducible results. |

Returns:

| Type                      | Description                                                                                                 |
| ------------------------- | ----------------------------------------------------------------------------------------------------------- |
| `tuple[ndarray, ndarray]` | The pair (X, y), with X of shape (n_samples, n_features) and y of shape (n_samples,), both of type float32. |

### `generate_timeseries(n_samples=300, kind='sine', noise=0.05, random_state=42)`

Generate a 1-D time series, as the pair `(t, y)`.

Parameters:

| Name           | Type    | Description                                                                                                                  | Default                                    |
| -------------- | ------- | ---------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------ |
| `n_samples`    | `int`   | The number of time steps.                                                                                                    | `300`                                      |
| `kind`         | `str`   | The shape of the series: "sine" for a sine wave with noise, or "ar" for an autoregressive process of order 1, written AR(1). | `'sine'`                                   |
| `noise`        | `float` | The standard deviation of the Gaussian noise.                                                                                | `0.05`                                     |
| `random_state` | \`int   | None\`                                                                                                                       | The random seed, for reproducible results. |

Returns:

| Type                      | Description                                                                                                                                                                                                |
| ------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `tuple[ndarray, ndarray]` | The pair (t, y), two arrays of shape (n_samples,) and type float32. t holds time values spaced evenly in [0, 1], and y is the signal. The arrays are not cut into windows, because the algorithms do that. |

### `get_dataset_info(name)`

Return the `DatasetInfo` of a dataset.

Parameters:

| Name   | Type  | Description                         | Default    |
| ------ | ----- | ----------------------------------- | ---------- |
| `name` | `str` | The key of the dataset in REGISTRY. | *required* |

Returns:

| Type          | Description                  |
| ------------- | ---------------------------- |
| `DatasetInfo` | The metadata of the dataset. |

Raises:

| Type         | Description                                                             |
| ------------ | ----------------------------------------------------------------------- |
| `ValueError` | If name is not in the registry. The message lists every available name. |

Example

```python
info = get_dataset_info("iris")
```

### `list_datasets()`

Return the metadata of every available dataset.

Returns:

| Type                | Description                                       |
| ------------------- | ------------------------------------------------- |
| `list[DatasetInfo]` | One DatasetInfo for each dataset in the registry. |

Example

```python
datasets = list_datasets()
print(datasets[0].name)  # 'breast_cancer_wisconsin'
```

### `load_dataset(name, *, split=True, test_size=0.2, validation_size=0.0, random_state=42, cache_dir=None)`

Load a dataset by name.

Parameters:

| Name              | Type    | Description                                                                                               | Default                                                                        |
| ----------------- | ------- | --------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------ |
| `name`            | `str`   | The name of the dataset in REGISTRY, for example "iris".                                                  | *required*                                                                     |
| `split`           | `bool`  | If True, the default, the data is split into a training set and a test set.                               | `True`                                                                         |
| `test_size`       | `float` | The fraction of the samples used for the test set.                                                        | `0.2`                                                                          |
| `validation_size` | `float` | The fraction of the samples used for the validation set. With 0, the default, there is no validation set. | `0.0`                                                                          |
| `random_state`    | \`int   | None\`                                                                                                    | The random seed of the split, and of the generator for the synthetic datasets. |
| `cache_dir`       | \`str   | None\`                                                                                                    | A cache directory for the downloaded datasets, in place of the default one.    |

Returns:

| Type   | Description                                                                                                                                                                                                                                                                                                                                                 |
| ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `dict` | A dictionary with these keys: With split=True: "X_train", "y_train", "X_test", "y_test" and "metadata", and also "X_val" and "y_val" when validation_size is above 0. With split=False: "X", "y" and "metadata". The synthetic time-series datasets also have a "sequence" key, which holds the whole series. "metadata" is the DatasetInfo of the dataset. |

Raises:

| Type         | Description                                                                                                                           |
| ------------ | ------------------------------------------------------------------------------------------------------------------------------------- |
| `ValueError` | If name is not in the registry, if validation_size is not in \[0, 1), or if test_size + validation_size is 1 or more with split=True. |

Example

```python
data = load_dataset("iris")
X_train, y_train = data["X_train"], data["y_train"]
```

### `rc_params(theme='light')`

Return the matplotlib settings of the library for one plot, as rcParams.

Every figure that the library draws uses these settings: `DatasetReport.plot_overview()`, the benchmark curves and the plots in the worked examples. This is what makes them look like one set. Pass the result to `matplotlib.rc_context()` and draw as usual. The settings apply only inside that block, because the returned dictionary is a new copy and the global `matplotlib.rcParams` is never changed.

The two themes differ only in what has to change for a dark page. `"dark"` makes the backgrounds of the figure, the axes and the legend transparent, and makes the text, the ticks and the spines white. The sizes, the spines, the grid and STYLE_COLORS are the same in both themes, so a figure saved with each theme differs only in its background and in the colour of its text and lines.

Parameters:

| Name    | Type  | Description                                                         | Default   |
| ------- | ----- | ------------------------------------------------------------------- | --------- |
| `theme` | `str` | "light" or "dark". The case and any surrounding spaces are ignored. | `'light'` |

Returns:

| Type   | Description                                                   |
| ------ | ------------------------------------------------------------- |
| `dict` | The rcParams to draw with, ready for matplotlib.rc_context(). |

Raises:

| Type         | Description                             |
| ------------ | --------------------------------------- |
| `ValueError` | If theme is neither "light" nor "dark". |

Example

```python
import matplotlib
import matplotlib.pyplot as plt
from eigenkit.datasets import STYLE_COLORS, rc_params

with matplotlib.rc_context(rc_params(theme="light")):
    fig, ax = plt.subplots(figsize=(7, 4))
    ax.plot(history, color=STYLE_COLORS[0], label="train loss")
    ax.legend()
    fig.savefig("loss.png", bbox_inches="tight")
```
