예제 #1
0
    def test_debug(self):
        """
        Test the debugging output of the MSC
        """
        self.setup()

        test_file = "msc_test_debug.txt"
        sys.stdout = open(test_file, "w")

        self.test_object = topopy.MorseSmaleComplex(debug=True,
                                                    graph=self.graph)
        self.test_object.build(self.X, self.Y)

        sys.stdout.close()
        lines = [
            "Graph Preparation:",
            "Decomposition:",
            "Stable Decomposition:",
            "Unstable Decomposition:",
        ]

        with open(test_file, "r") as fp:
            debug_output = fp.read()
            for line in lines:
                self.assertIn(line, debug_output)

        os.remove(test_file)
        # Restore stdout
        sys.stdout = sys.__stdout__
예제 #2
0
    def test_unstructured(self):
        """
        Tests functionality on something other than a regular grid
        """
        self.X = np.array([[0, 0], [1, 1], [1, 0], [0, 1], [0.25, 0.25],
                           [0.25, 0.75], [0.75, 0.75], [0.75, 0.25],
                           [0.0, 0.6], [0.0, 0.25], [0.0, 0.75], [0.25, 0.0],
                           [0.6, 0.0], [0.6, 0.25], [0.625, 0.55], [0.6, 0.75],
                           [0.75, 0.0], [0.25, 0.55], [1, 0.25], [0.65, 1],
                           [1, 0.55], [1, 0.75], [0.75, 1], [0.25, 1],
                           [0.75, 0.6]])
        self.Y = gerber(self.X)

        self.test_object = topopy.MorseSmaleComplex(
            gradient="steepest",
            normalization=None,
            simplification="difference",
            aggregator=None,
            debug=False,
        )
        self.test_object.build(self.X, self.Y)

        self.assertEqual(
            13,
            len(self.test_object.get_merge_sequence()),
            "The merge sequence does not match the expected output.",
        )
예제 #3
0
    def setup(self):
        """
        Setup function will create a fixed point set and parameter
        settings for testing different aspects of this library.
        """
        self.X = generate_test_grid_2d(40)
        self.Y = gerber(self.X)
        self.graph = ngl.EmptyRegionGraph(max_neighbors=10)

        self.norm_x = {}
        scaler = sklearn.preprocessing.MinMaxScaler()
        self.norm_x["feature"] = scaler.fit_transform(np.atleast_2d(self.X))
        self.norm_x["zscore"] = sklearn.preprocessing.scale(self.X,
                                                            axis=0,
                                                            with_mean=True,
                                                            with_std=True,
                                                            copy=True)
        self.norm_x["none"] = self.X

        # Methods covered here:
        # __init__
        # build
        # __set_data
        self.test_object = topopy.MorseSmaleComplex(debug=False,
                                                    graph=self.graph)
        self.test_object.build(self.X, self.Y)

        gold_path = os.path.join("topopy", "tests", "msc_gold.json")
        with open(gold_path, "r") as data_file:
            gold_json = data_file.read()
            gold_json = json.loads(gold_json)
        self.gold = gold_json
예제 #4
0
    def test_load_data_and_build(self):
        """
        Tests that loading the same test data from file yields an
        equivalent result
        """
        self.setup()

        local_object = topopy.MorseSmaleComplex()

        np.savetxt(
            "test_file.csv",
            np.hstack((self.X, np.atleast_2d(self.Y).T)),
            delimiter=",",
            header="x0,x1,y",
        )
        local_object.load_data_and_build("test_file.csv", delimiter=",")
        os.remove("test_file.csv")

        self.assertDictEqual(
            self.test_object.merge_sequence,
            local_object.merge_sequence,
            "loading from file should produce the same hierarchy",
        )
        self.assertSetEqual(
            set(self.test_object.base_partitions.keys()),
            set(local_object.base_partitions.keys()),
            "loading from file should produce the base partitions.",
        )

        for key in self.test_object.base_partitions.keys():
            self.assertListEqual(
                self.test_object.base_partitions[key].tolist(),
                local_object.base_partitions[key].tolist(),
                "loading from file should produce the base partitions.",
            )
예제 #5
0
def color_msc(X, Y, p):
    msc = topopy.MorseSmaleComplex(max_neighbors=8, graph="beta skeleton")
    msc.build(X, Y)

    partitions = msc.get_partitions(p)
    unique_keys = partitions.keys()
    encoded_keys = {}
    next_value = 0

    for key in unique_keys:
        encoded_keys[key] = next_value
        next_value = (next_value + 1) % unique_colors

    C = np.zeros(len(X))
    for key, items in partitions.items():
        C[list(items)] = encoded_keys[key]

    return C
예제 #6
0
    def test_get_partitions(self):
        self.setup()

        gold_msc_partitions = {}
        gold_stable_partitions = {}
        gold_unstable_partitions = {}
        for i, (min_label, max_label) in enumerate(self.gold["Partitions"]):
            if max_label not in gold_stable_partitions:
                gold_stable_partitions[max_label] = []
            gold_stable_partitions[max_label].append(i)

            if min_label not in gold_unstable_partitions:
                gold_unstable_partitions[min_label] = []
            gold_unstable_partitions[min_label].append(i)

            if (min_label, max_label) not in gold_msc_partitions:
                gold_msc_partitions[(min_label, max_label)] = []
            gold_msc_partitions[(min_label, max_label)].append(i)

        partitions = self.test_object.get_partitions()
        self.assertEqual(
            16,
            len(partitions),
            "The number of partitions "
            "without specifying the "
            "persistence should be the "
            "same as requesting the base "
            "(0) persistence level",
        )

        self.assertDictEqual(
            gold_msc_partitions,
            partitions,
            "The base partitions of the Morse-Smale complex should match",
        )

        partitions = self.test_object.get_stable_manifolds()
        self.assertEqual(
            4,
            len(partitions),
            "The number of stable manifolds should be 4 at the base level",
        )
        self.assertDictEqual(
            gold_stable_partitions,
            partitions,
            "The base partitions of the stable manifolds should match",
        )

        partitions = self.test_object.get_unstable_manifolds()
        self.assertEqual(
            9,
            len(partitions),
            "The number of unstable manifolds should be 9 at the base level",
        )
        self.assertDictEqual(
            gold_unstable_partitions,
            partitions,
            "The base partitions of the unstable manifolds should match",
        )

        test_p = 0.5

        merge_pattern = {}
        # Initialize every extrema to point to itself
        for merge in self.gold["Hierarchy"]:
            merge_pattern[merge["Dying"]] = merge["Dying"]

        # Now point to the correct label for the specified persistence
        for merge in self.gold["Hierarchy"]:
            if merge["Persistence"] < test_p:
                if merge["Surviving"] not in merge_pattern:
                    merge_pattern[merge["Surviving"]] = merge["Surviving"]
                merge_pattern[merge["Dying"]] = merge_pattern[
                    merge["Surviving"]]

        gold_msc_partitions = {}
        gold_stable_partitions = {}
        gold_unstable_partitions = {}
        for i, (min_label, max_label) in enumerate(self.gold["Partitions"]):
            min_label = merge_pattern[min_label]
            max_label = merge_pattern[max_label]

            if max_label not in gold_stable_partitions:
                gold_stable_partitions[max_label] = []
            gold_stable_partitions[max_label].append(i)

            if min_label not in gold_unstable_partitions:
                gold_unstable_partitions[min_label] = []
            gold_unstable_partitions[min_label].append(i)

            if (min_label, max_label) not in gold_msc_partitions:
                gold_msc_partitions[(min_label, max_label)] = []
            gold_msc_partitions[(min_label, max_label)].append(i)

        partitions = self.test_object.get_partitions(test_p)
        self.assertEqual(
            4,
            len(partitions),
            "The number of partitions at the 0.5 level should be 4",
        )
        self.assertDictEqual(
            gold_msc_partitions,
            partitions,
            "The partitions of the Morse-Samle complex should match at "
            "the test level p={}".format(test_p),
        )

        partitions = self.test_object.get_stable_manifolds(test_p)
        self.assertEqual(
            1,
            len(partitions),
            "The number of stable manifolds should be 1 at the test "
            "level p={}".format(test_p),
        )
        self.assertDictEqual(
            gold_stable_partitions,
            partitions,
            "The base partitions of the stable manifolds should match "
            "at the test level p={}".format(test_p),
        )

        partitions = self.test_object.get_unstable_manifolds(0.5)
        self.assertEqual(
            4,
            len(partitions),
            "The number of unstable manifolds should be 9 at the test "
            "level p={}".format(test_p),
        )
        self.assertDictEqual(
            gold_unstable_partitions,
            partitions,
            "The base partitions of the unstable manifolds should "
            "match at the test level p={}".format(test_p),
        )

        self.test_object = topopy.MorseSmaleComplex()
        partitions = self.test_object.get_partitions()
        self.assertEqual(
            {},
            partitions,
            "Requesting partitions on an unbuilt object should return "
            "an empty dict",
        )
예제 #7
0
    mag = np.linalg.norm(grad_x)
    if mag < stopping_crieterion:
        return np.array([0, 0]).flatten()
    return grad_x / mag * step_size


x, y = np.mgrid[min_x:max_x:(resolution * 1j), min_x:max_x:(resolution * 1j)]
X = np.vstack([x.ravel(), y.ravel()]).T

Z = np.empty(X.shape[0])
for i, xi in enumerate(X):
    Z[i] = test_function(xi)
z = Z.reshape(x.shape)

start = time.time()
msc = topopy.MorseSmaleComplex(max_neighbors=8, graph="beta skeleton")
msc.build(X, Z)
msc.set_persistence(p)
end = time.time()
print("Build MSC: {} s".format(end - start))
start = time.time()

mins = []
maxs = []
saddles = []
saddle_ptrs = {}
for key in msc.get_partitions().keys():
    mins.append(key[0])
    maxs.append(key[1])

json_object = json.loads(msc.to_json())