Assigns data to this object and builds the Morse-Smale
            Complex
            @ In, X, an m-by-n array of values specifying m
            n-dimensional samples
            @ In, Y, a m vector of values specifying the output
            responses corresponding to the m samples specified by X
            @ In, w, an optional m vector of values specifying the
            weights associated to each of the m samples used. Default of
            None means all points will be equally weighted
            @ In, edges, an optional list of custom edges to use as a
            starting point for pruning, or in place of a computed graph.

def build(self, X, Y, w=None, edges=None):
        """ Assigns data to this object and builds the Morse-Smale
            Complex
            @ In, X, an m-by-n array of values specifying m
            n-dimensional samples
            @ In, Y, a m vector of values specifying the output
            responses corresponding to the m samples specified by X
            @ In, w, an optional m vector of values specifying the
            weights associated to each of the m samples used. Default of
            None means all points will be equally weighted
            @ In, edges, an optional list of custom edges to use as a
            starting point for pruning, or in place of a computed graph.
        """
        super(MorseSmaleComplex, self).build(X, Y, w, edges)

        if self.debug:
            sys.stdout.write("Decomposition: ")
            start = time.clock()

        stableManifolds = MorseComplex(debug=self.debug)
        unstableManifolds = MorseComplex(debug=self.debug)

        stableManifolds.build_for_morse_smale_complex(self, False)
        unstableManifolds.build_for_morse_smale_complex(self, True)

        self.min_indices = unstableManifolds.max_indices
        self.max_indices = stableManifolds.max_indices

        # If a degenerate point is both a minimum and a maximum, it
        # could potentially appear twice, but would be masked by the
        # minimum key which would wipe the maximum merge
        self.merge_sequence = stableManifolds.merge_sequence.copy()
        self.merge_sequence.update(unstableManifolds.merge_sequence)
        self.persistences = sorted(
            stableManifolds.persistences + unstableManifolds.persistences
        )

        self.base_partitions = {}
        base = np.array([[None, None]] * len(Y))
        for key, items in unstableManifolds.base_partitions.items():
            base[np.array(items), 0] = key
        for key, items in stableManifolds.base_partitions.items():
            base[np.array(items), 1] = key

        keys = set(map(tuple, base))
        for key in keys:
            self.base_partitions[key] = np.where(
                np.logical_and(base[:, 0] == key[0], base[:, 1] == key[1])
            )[0]

        if self.debug:
            end = time.clock()
            sys.stdout.write("%f s\n" % (end - start))