.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "examples/custom_cover.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code. .. rst-class:: sphx-glr-example-title .. _sphx_glr_examples_custom_cover.py: Creating a custom cover ----------------------- This example will go over the API for creating a custom cover scheme. We will be implementing the epsilon nets outlined in https://arxiv.org/abs/1901.07410. This is meant to illustrate the expected api, not much thought was put into the actual implementation of the cover itself and there may be better ways. .. GENERATED FROM PYTHON SOURCE LINES 12-17 Constructing a cover ==================== We will start by defining an epsilon-net function. This will take a list of centers, an epsilon, and a data array and return a list of numpy arrays. .. GENERATED FROM PYTHON SOURCE LINES 17-38 .. code-block:: Python import numpy as np import zen_mapper as zm def epsilon_net(centers, epsilon, data) -> list[np.ndarray]: if len(data.shape) == 1: data.reshape(-1, 1) result = [] for center in centers: current = [] for i, datum in enumerate(data): if np.sum((center - datum) ** 2) < epsilon**2: current.append(i) result.append(np.array(current, dtype=int)) return result .. GENERATED FROM PYTHON SOURCE LINES 39-43 It is worth noting that :class:`list[np.ndarray]` implements the :class:`Cover ` protocol and so `epsilon_net` is returning a valid `zen_mapper` cover. We can then visualize that this cover acts as we hope it would .. GENERATED FROM PYTHON SOURCE LINES 43-64 .. code-block:: Python import matplotlib.pyplot as plt data = np.c_[np.arange(11), np.arange(11)] centers = np.array([[5, 5], [3, 3]]) epsilon = 2 ax = plt.gca() ax.scatter(data[:, 0], data[:, 1]) cover = epsilon_net(centers, epsilon, data) for element in cover: ax.scatter(data[element, 0], data[element, 1]) for center in centers: circ = plt.Circle(center, epsilon, color="r", fill=False) ax.add_patch(circ) ax.set_aspect("equal") plt.show() .. image-sg:: /examples/images/sphx_glr_custom_cover_001.png :alt: custom cover :srcset: /examples/images/sphx_glr_custom_cover_001.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 65-73 Creating a covering scheme ========================== The mapper function in zen_mapper expects a `covering_scheme` which is simply a function which takes data and returns a cover. I find pythons partial function support to be kind of awkward. So instead of defining a function we will define a class with the `__call__` method which python will treat like a function. .. GENERATED FROM PYTHON SOURCE LINES 73-101 .. code-block:: Python class Greedy_Epsilon_Net: def __init__(self, epsilon: float): self.epsilon = epsilon self.centers = None def __call__(self, data: np.ndarray) -> list[np.ndarray]: to_cover = set(range(len(data))) centers = [] while to_cover: new_center = to_cover.pop() centers.append(data[new_center]) covered = set() for point in to_cover: if np.sum((data[new_center] - data[point]) ** 2) < self.epsilon**2: covered.add(point) to_cover -= covered self.centers = centers return epsilon_net(centers, self.epsilon, data) .. GENERATED FROM PYTHON SOURCE LINES 102-103 we can then visualize the covering scheme in much the same way we visualized the cover .. GENERATED FROM PYTHON SOURCE LINES 103-121 .. code-block:: Python data = np.c_[np.arange(11), np.arange(11)] scheme = Greedy_Epsilon_Net(epsilon=2) ax = plt.gca() ax.scatter(data[:, 0], data[:, 1]) cover = scheme(data) for element in cover: ax.scatter(data[element, 0], data[element, 1]) for center in scheme.centers: circ = plt.Circle(center, epsilon, color="r", fill=False) ax.add_patch(circ) ax.set_aspect("equal") plt.show() .. image-sg:: /examples/images/sphx_glr_custom_cover_002.png :alt: custom cover :srcset: /examples/images/sphx_glr_custom_cover_002.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 122-128 Using with mapper ================= Now that we have a cover we will demonstrate how to plug it into zen mapper to duplicate the analysis done in the original paper. We will be using a similar window dataset to the one they used. We start by generating our data. .. GENERATED FROM PYTHON SOURCE LINES 128-144 .. code-block:: Python def window(num_samples: int) -> np.ndarray: data = np.random.rand(num_samples, 2) data[:, 1] *= 9 data[:, 0] += 4 * np.random.randint(0, 3, size=num_samples) choice = np.random.randint(0, 2, size=(num_samples, 1)) return choice * data + (1 - choice) * data[:, [1, 0]] np.random.seed(42) data = window(1000) plt.scatter(data[:, 0], data[:, 1]) plt.gca().set_aspect("equal") plt.show() .. image-sg:: /examples/images/sphx_glr_custom_cover_003.png :alt: custom cover :srcset: /examples/images/sphx_glr_custom_cover_003.png :class: sphx-glr-single-img .. GENERATED FROM PYTHON SOURCE LINES 145-148 We also need to define a clustering algorithm. In this paper they don't actually cluster anything, instead any datapoint in the ball is deemed to be connected. So we define the following trivial clusterer. .. GENERATED FROM PYTHON SOURCE LINES 148-154 .. code-block:: Python def trivial(data: np.ndarray): return [np.arange(len(data))], None .. GENERATED FROM PYTHON SOURCE LINES 155-157 With this we are able to call mapper and get a very similar graph to the one from the paper. .. GENERATED FROM PYTHON SOURCE LINES 157-171 .. code-block:: Python import networkx as nx result = zm.mapper( data=data, projection=data, cover_scheme=Greedy_Epsilon_Net(1), clusterer=trivial, dim=1, ) g = zm.to_networkx(result.nerve) nx.draw_kamada_kawai(g) plt.show() .. image-sg:: /examples/images/sphx_glr_custom_cover_004.png :alt: custom cover :srcset: /examples/images/sphx_glr_custom_cover_004.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 0.528 seconds) .. _sphx_glr_download_examples_custom_cover.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: custom_cover.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: custom_cover.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: custom_cover.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_