コード例 #1
0
 def run(self, args):
     d = self.median_filter(ld.LinearDecomposition().load(args.infile),
                            args.window, False)
     meta = md.FileMetadata(args.infile)
     for k, data, metadata in d.right():
         metadata.activation_input = meta
     d.save(args.outfile)
コード例 #2
0
ファイル: mean.py プロジェクト: templeblock/pymir3
    def compute(self,
                s,
                note,
                instrument,
                number_frames=10,
                frame_skip=2,
                save_metadata=True):
        """Builds a basis from the mean of a spectrogram.

        Uses a part of the spectrogram to compute the mean value.

        Args:
            s: Spectrogram object.
            note: note's name.
            instrument: instrument's name.
            number_frames: number of frames to use. Default: 10.
            frame_skip: number of frames to skip after the attack. Default: 2.
            save_metadata: flag indicating whether the metadata should be
                           computed. Default: True.

        Returns:
            LinearDecomposition object with the window's mean on the left.
        """
        data = s.data

        # Detects attack
        energy = numpy.sum(data, 0)
        energy_peak = numpy.argmax(energy)

        # Max number of frames availables
        max_frames = numpy.size(data, 1)

        # Avoids getting less frames because data ended
        if energy_peak > (max_frames - number_frames - frame_skip - 1):
            energy_peak = max_frames - number_frames - frame_skip - 1

        # But if there's enough data, skip a few frames after energy peak
        else:
            energy_peak += frame_skip

        # Cuts data
        data = data[:, energy_peak:energy_peak + number_frames]

        # Computes the mean
        data = numpy.array([numpy.mean(data, 1)]).transpose()

        # Saves metadata
        input_metadata = md.ObjectMetadata(s) if save_metadata else None

        # Stores the basis as a decompositon
        d = ld.LinearDecomposition()
        d.add((instrument, note),
              left=data,
              left_metadata=md.Metadata(method='mean',
                                        number_of_frames=number_frames,
                                        frame_skip=frame_skip,
                                        spectrogram=s.metadata,
                                        spectrogram_input=input_metadata))

        return d
コード例 #3
0
    def extract(self, d, side):
        """Extracts one side of a linear decomposition.

        The variables are only assigned, not copied. Any change to one object
        affects both the input and output.

        Args:
            d: LinearDecomposition object.
            side: name of the side that must be kept. Must be 'left' or 'right'.

        Returns:
            new LinearDecomposition object with the other side clear.

        Raises:
            ValueError: argument 'side' isn't either 'left' or 'right'.
        """
        new_d = ld.LinearDecomposition()

        if side == 'left':
            new_d.data.left = d.data.left
            new_d.metadata.left = d.metadata.left
        elif side == 'right':
            new_d.data.right = d.data.right
            new_d.metadata.right = d.metadata.right
        else:
            raise ValueError("Invalid side '%r'." % side)

        return new_d
コード例 #4
0
ファイル: elbow.py プロジェクト: templeblock/pymir3
    def find_best_elbow(self, args):
        best_file_name = None
        best_elbow = -1.0
        this_elbow = 0
        th_list = []
        for filename in args.infile:
            with open(filename, 'rb') as handler:
                a = ld.LinearDecomposition().load(handler)
                # Stack periodicities for all instruments:
                full_data = None
                for k in a.data.right.keys():
                    if full_data is None:
                        full_data = a.data.right[k]
                    else:
                        full_data = numpy.vstack( (full_data,\
                            a.data.right[k]))

                frac = numpy.sum(full_data) /\
                        (full_data.shape[0] * full_data.shape[1])

                th_list.append([frac, filename])

        th_list.sort(key=lambda x: x[0])

        for i in xrange(len(th_list) - 2):
            this_elbow = self.knee(th_list[i][0], th_list[i+1][0],\
                    th_list[i+2][0])

            if this_elbow > best_elbow:
                best_elbow = this_elbow
                best_file_name = th_list[i + 3][1]

        print best_file_name
コード例 #5
0
    def run(self, args):
        # Loads basis if present
        if args.basis is not None:
            b = ld.LinearDecomposition().load(args.basis)
        else:
            b = None

        if args.basis is not None and b.data.right != {}:
            print "Basis doesn't have empty right side. Ignoring it."

        # Size of the decomposition (used when finding a basis too)
        if args.size is None:
            args.size = [None, None, None] # Simulate 3 values
        for i in range(len(args.size)):
            if args.size[i] == 'None' or args.size[i] == 'null':
                args.size[i] = None

        # Gather input spectrograms
        s_list = []
        s_meta = []
        for filename in args.piece:
            with open(filename, 'rb') as handler:
                s_list.append(spectrogram.Spectrogram().load(handler))
                s_meta.append(md.FileMetadata(handler))

        # Converts arguments
        size = int(args.size[0]) if args.size[0] is not None else None
        instrument = args.size[1] if args.size[1] is not None else ''
        note = args.size[2] if args.size[2] is not None else ''

        # Decompose
        d = self.compute(s_list,
                         size,
                         instrument,
                         note,
                         b,
                         args.beta,
                         args.min_delta,
                         args.max_iterations,
                         False)

        # Associates an activation metadata with its given spectrogram's
        # metadata
        for k, data, metadata in d.right():
            metadata.spectrogram_input = s_meta[k[-1]]

        # Checks if basis was provided
        if b is not None:
            # If provided, adds it as basis metadata for each activation
            meta = md.FileMetadata(args.basis)
            for k, data, metadata in d.right():
                metadata.basis_input = meta
        else:
            # Otherwise, the basis was computed right now, so we set its
            # metadata with the list of all spectrograms' metadata
            d.metadata.left[(args.size[1], args.size[2])].spectrogram_input = \
                    s_meta

        d.save(args.outfile)
コード例 #6
0
ファイル: hard-sparsity.py プロジェクト: templeblock/pymir3
 def run(self, args):
     d = self.hard_sparsity(ld.LinearDecomposition().load(args.infile),
                       args.sparsity,
                       False)
     meta = md.FileMetadata(args.infile)
     for k, data, metadata in d.right():
         metadata.activation_input = meta
     d.save(args.outfile)
コード例 #7
0
    def run(self, args):
        d_list = []
        for filename in args.infile:
            with open(filename, 'rb') as handler:
                d_list.append(ld.LinearDecomposition().load(handler))

        new_d = self.merge(d_list)

        new_d.save(args.outfile)
コード例 #8
0
ファイル: tests.py プロジェクト: templeblock/pymir3
    def run(self, args):
        decompositions = []
        for filename in args.infile:
            with open(filename, 'rb') as handler:
                decompositions.append(ld.LinearDecomposition().load(handler))

        for level in self.get_levels(decompositions, args.number_values,
                                     args.use_max):
            print level
コード例 #9
0
    def merge(self, decompositions_list):
        """Merges the linear decompositions given into a single one.

        Args:
            decompositions_list: a list of linear decompositions to be merged.

        Returns:
            LinearDecomposition object with inputs merged.
        """
        d = ld.LinearDecomposition()

        for other in decompositions_list:
            for key, data, metadata in other.left():
                d.add(key, left=data, left_metadata=metadata)
            for key, data, metadata in other.right():
                d.add(key, right=data, right_metadata=metadata)

        return d
コード例 #10
0
    def find_best_periodicity(self, args):
        best_file_name = None
        best_periodicity = -1.0
        this_periodicity = 0.0
        for filename in args.infile:
            with open(filename, 'rb') as handler:
                a = ld.LinearDecomposition().load(handler)

                # Stack periodicities for all instruments:
                full_data = None
                for k in a.data.right.keys():
                    if full_data is None:
                        full_data = a.data.right[k]
                    else:
                        full_data = numpy.vstack( (full_data,\
                            a.data.right[k]))

                this_periodicity = per.periodicity(full_data, e=args.exponent)
                if this_periodicity > best_periodicity:
                    best_periodicity = this_periodicity
                    best_file_name = filename

        print best_file_name
コード例 #11
0
 def run(self, args):
     s = self.convert(ld.LinearDecomposition().load(args.infile),
                      args.instrument, args.frequency, args.minimum_length,
                      False)
     s.metadata.input = md.FileMetadata(args.infile)
     s.save(args.outfile)
コード例 #12
0
 def run(self, args):
     d = ld.LinearDecomposition().load(args.infile)
     new_d = self.extract(d, args.side)
     new_d.save(args.outfile)
コード例 #13
0
ファイル: max_basis.py プロジェクト: templeblock/pymir3
 def run(self, args):
     d = self.compute(ld.LinearDecomposition().load(args.infile))
     d.save(args.outfile)
コード例 #14
0
    def compute(self, spectrograms, size=None, instrument=None, note=None,
                basis=None, beta=2., min_delta=0., max_iterations=100,
                save_metadata=True):
        """Computes the activation matrix from a basis matrix and a spectrogram.

        Uses the beta divergence to compute the activations.

        If min_delta is zero, the code may run faster because no beta divergence
        is actually computed. Otherwise, the code stops computing if two
        iterations of the algorithm don't improve the result by more than
        min_delta.

        Only one of 'basis' and 'size' arguments may be set, as they specify
        different things. With 'size', the user extracts both a basis and an
        activation from the spectrogram, while with 'basis' only an activation
        is computed.

        Each activation computed has the same key as the corresponding basis
        plus the spectrogram's index in the list provided.

        If a basis is being created, it's name is a tuple of (instrument, note),
        even if they are None.

        Args:
            spectrograms: list of Spectrograms to be merged and used to compute
                          the activations.
            size: Number of basis to extract from the spectrogram. Must be None
                  if the 'basis' argument is defined.
            instrument: Name of the instrument. This is used only if size is
                        set. If None, it's ignored. Default: None.
            note: Name of the note. This is used only if size is set. If None,
                  it's ignored. Default: None.
            basis: LinearDecomposition object describing the basis to be used.
                   Must be none if the 'size' argument is defined.
            beta: value for the beta used in divergence. Default: 2.
            min_delta: threshold for early stop. Default: 0.
            max_iterations: maximum number of iterations to use. Default: 100.
            save_metadata: flag indicating whether the metadata should be
                           computed. Default: True.

        Returns:
            LinearDecomposition object with basis and activations for the
            spectrograms.

        Raises:
            ValueError: matrices have incompatible sizes.
        """
        # Check arguments compatibility
        if size is None and basis is None:
            raise ValueError("One of 'size' or 'basis' must not be None.")

        if basis is not None and size is not None:
            raise ValueError("Only one of 'size' or 'basis' must not be None.")

        # Saves metadata
        if save_metadata:
            s_meta = [md.ObjectMetadata(s) for s in spectrograms]
        else:
            s_meta = [None for s in spectrograms]

        # Marks the limits of each spectrogram
        X_start = [0]
        for s in spectrograms:
            X_start.append(X_start[-1]+s.data.shape[1])

        # Merges spectrograms
        X = numpy.hstack([s.data for s in spectrograms])

        # If we have a basis, we only need to compute the activations
        if basis is not None:
            # Merges basis but keep track where each one starts so that it can
            # be used to characterize the activations
            B = []
            B_start = [0]
            for k, data, metadata in basis.left():
                B.append(data)
                B_start.append(B_start[-1]+data.shape[1])
            B = numpy.hstack(B)

            # Saves metadata
            if save_metadata:
                b_meta = md.ObjectMetadata(B)
            else:
                b_meta = None

            # Initilizes activations
            A = numpy.ones((B.shape[1], X.shape[1]))

            # Computes the activation
            self.compute_activation(X, B, A, beta, min_delta, max_iterations)

            # Starts creating the decomposition object
            d = ld.LinearDecomposition()

            # Copy the left stuff from the basis, since they came from there
            d.data.left = basis.data.left
            d.metadata.left = basis.metadata.left

            # Cuts the activation. For each combination of basis and
            # spectrograms, we get an activation
            i = 0
            for k, data, metadata in basis.left():
                for j in range(len(spectrograms)):
                    # Since spectrograms don't have name, we call it by its
                    # sequence number
                    s_name = (j,)

                    # Cuts the activation
                    A_cut = A[B_start[i]:B_start[i+1], X_start[j]:X_start[j+1]]

                    # Merges the basis key with the spectrogram name to create a
                    # key for the activation. Then stores a lot of metadata
                    # about what was used to compute it.
                    d.add(k+s_name,
                          right=A_cut,
                          right_metadata=md.Metadata(
                              method="beta_nmf",
                              beta=beta,
                              min_delta=min_delta,
                              max_iterations=max_iterations,
                              spectrogram_input=s_meta[j],
                              spectrogram=s.metadata,
                              basis_input=b_meta,
                              basis=metadata))

                # Increase basis iterator
                i += 1
        else:
            # Everyone gets the same matrices to work with every time, so we
            # avoid consistency problems. However, we can't have the same values
            # filling the matrices or the algorithm can't separate the basis and
            # activations (everyone keeps getting the same value).
            numpy.random.seed(0)
            B = numpy.random.rand(X.shape[0], size)
            A = numpy.random.rand(size, X.shape[1])

            # Computes both basis and activations
            self.compute_both(X, B, A, beta, min_delta, max_iterations)

            # Key for the basis created
            key = (instrument, note)

            # Starts creating the decomposition object
            d = ld.LinearDecomposition()

            # Adds basis
            d.add(key,
                  left=B,
                  left_metadata=md.Metadata(
                      method="beta_nmf",
                      beta=beta,
                      min_delta=min_delta,
                      max_iterations=max_iterations,
                      spectrogram_input=s_meta,
                      spectrogram=[s.metadata for s in spectrograms]))

            # Adds the activations cutted to match the spectrograms
            for j in range(len(spectrograms)):
                # Since spectrograms don't have name, we call it by its sequence
                # number
                s = spectrograms[j]
                s_name = (j,)

                # Cuts the activation
                A_cut = A[:, X_start[j]:X_start[j+1]]

                # Merges the basis key with the spectrogram name to create a key
                # for the activation. Then stores a lot of metadata about what
                # was used to compute it.
                d.add(key+s_name,
                      right=A_cut,
                      right_metadata=md.Metadata(
                          method="beta_nmf",
                          beta=beta,
                          min_delta=min_delta,
                          max_iterations=max_iterations,
                          spectrogram_input=s_meta[j],
                          spectrogram=s.metadata))

        return d