def test_intervs_3(self, mock_guc, mock_rfa, mock_rep):
        """Ensure _intervs() calls everything in the right order, with the right args & settings.
           This uses the default *except* requires removing rests, so it's more complex."""
        test_settings = {'simple or compound': 'compound', 'quality': False}
        test_pieces = [MagicMock(spec_set=IndexedPiece) for _ in range(3)]
        returns = [
            pandas.DataFrame([pandas.Series(['3', 'Rest', '5'])],
                             index=[['interval.IntervalIndexer'], ['0,1']]).T
            for i in range(len(test_pieces))
        ]
        for piece in test_pieces:
            piece.get_data.side_effect = lambda *x: returns.pop(0)
        exp_series_ind = ('interval.IntervalIndexer', '0,1')
        expected_df = pandas.DataFrame(
            {exp_series_ind: pandas.Series(['3', '5'], index=[0, 2])})
        exp_analyzers = [noterest.NoteRestIndexer, interval.IntervalIndexer]

        test_wc = WorkflowManager(test_pieces)
        test_wc.settings(None, 'count frequency', False)
        actual = test_wc._intervs()  # pylint: disable=protected-access

        self.assertEqual(0, mock_guc.call_count)
        self.assertEqual(len(test_pieces), len(actual))
        self.assertEqual(0, mock_rfa.call_count)
        self.assertEqual(0, mock_rep.call_count)
        for piece in test_pieces:
            piece.get_data.assert_called_once_with(exp_analyzers,
                                                   test_settings)
        for i in range(len(actual)):
            self.assertSequenceEqual(list(expected_df.columns),
                                     list(actual[i].columns))
            self.assertSequenceEqual(list(expected_df[exp_series_ind].index),
                                     list(actual[i][exp_series_ind].index))
            self.assertSequenceEqual(list(expected_df[exp_series_ind].values),
                                     list(actual[i][exp_series_ind].values))
    def test_intervs_1(self, mock_guc, mock_rfa, mock_rep):
        """Ensure _intervs() calls everything in the right order, with the right args & settings.
           This test uses all the default settings."""
        test_settings = {'simple or compound': 'compound', 'quality': False}
        test_pieces = [MagicMock(spec_set=IndexedPiece) for _ in range(3)]
        returns = ['get_data() {}'.format(i) for i in range(len(test_pieces))]
        for piece in test_pieces:
            piece.get_data.side_effect = lambda *x: returns.pop(0)
        expected = ['get_data() {}'.format(i) for i in range(len(test_pieces))]
        exp_analyzers = [noterest.NoteRestIndexer, interval.IntervalIndexer]

        test_wc = WorkflowManager(test_pieces)
        test_wc.settings(None, 'include rests', True)
        actual = test_wc._intervs()  # pylint: disable=protected-access

        self.assertEqual(0, mock_guc.call_count)
        self.assertEqual(len(test_pieces), len(expected), len(actual))
        self.assertEqual(0, mock_rep.call_count)
        mock_rfa.assert_called_once_with('interval.IntervalIndexer')
        for piece in test_pieces:
            piece.get_data.assert_called_once_with(exp_analyzers,
                                                   test_settings)
        for i in range(len(actual)):
            # NB: in real use, _run_freq_agg() would aggregate a piece's voice pairs and save it in
            #     self._result... but since that method's mocked out, we have to check here the
            #     return of each piece's get_data() call
            self.assertSequenceEqual(expected[i], actual[i])
예제 #3
0
 def test_intervals_2(self):
     """test all combinations of bwv77"""
     test_wm = WorkflowManager(
         [os.path.join(VIS_PATH, 'tests', 'corpus', 'bwv77.mxl')])
     test_wm.load('pieces')
     test_wm.settings(0, 'voice combinations', 'all pairs')
     actual = test_wm.run('intervals')
     self.assertEqual(1, len(actual.columns))
     actual = actual['aggregator.ColumnAggregator']
     exp_ind = list(IntervalsTests.EXPECTED_2.index)
     act_ind = list(actual.index)
     for ind_item in exp_ind:
         self.assertTrue(ind_item in act_ind)
     for ind_item in exp_ind:
         self.assertEqual(IntervalsTests.EXPECTED_2[ind_item],
                          actual[ind_item])
예제 #4
0
 def test_intervals_3(self):
     """test all combinations of madrigal51 without rests"""
     test_wm = WorkflowManager(
         [os.path.join(VIS_PATH, 'tests', 'corpus', 'madrigal51.mxl')])
     test_wm.load('pieces')
     test_wm.settings(0, 'voice combinations', 'all pairs')
     test_wm.settings(None, 'include rests', False)
     actual = test_wm.run('intervals')
     self.assertEqual(1, len(actual.columns))
     actual = actual['aggregator.ColumnAggregator']
     exp_ind = list(IntervalsTests.EXPECTED_3.index)
     act_ind = list(actual.index)
     for ind_item in exp_ind:
         self.assertTrue(ind_item in act_ind)
     for ind_item in exp_ind:
         self.assertEqual(IntervalsTests.EXPECTED_3[ind_item],
                          actual[ind_item])
    def test_intervs_4(self):
        """Ensure _intervs() fails when given an impossible 'voice pair'."""
        test_pieces = [MagicMock(spec_set=IndexedPiece) for _ in range(3)]
        returns = ['get_data() {}'.format(i) for i in range(len(test_pieces))]
        for piece in test_pieces:
            piece.get_data.side_effect = lambda *x: returns.pop(0)
        exp_err_msg = WorkflowManager._REQUIRE_PAIRS_ERROR.format(3)  # pylint: disable=protected-access

        test_wc = WorkflowManager(test_pieces)
        test_wc.settings(None, 'include rests', True)
        test_wc.settings(None, 'voice combinations',
                         '[[0, 1, 2]]')  # that's not a pair!

        self.assertRaises(RuntimeError, test_wc._intervs)  # pylint: disable=protected-access
        try:
            test_wc._intervs()  # pylint: disable=protected-access
        except RuntimeError as run_err:
            self.assertEqual(exp_err_msg, run_err.args[0])
    def test_intervs_2(self, mock_guc, mock_rfa, mock_rep):
        """Ensure _intervs() calls everything in the right order, with the right args & settings.
           Same as test_intervs_1() but:
              - calls _remove_extra_pairs(), and
              - doesn't call _run_freq_agg()."""
        mock_guc.return_value = [[0, 1]]
        voice_combos = str(mock_guc.return_value)
        exp_voice_combos = ['0,1']
        test_settings = {'simple or compound': 'compound', 'quality': False}
        test_pieces = [MagicMock(spec_set=IndexedPiece) for _ in range(3)]
        returns = ['get_data() {}'.format(i) for i in range(len(test_pieces))]
        for piece in test_pieces:
            piece.get_data.side_effect = lambda *x: returns.pop(0)
        exp_into_mock_rep = [
            'get_data() {}'.format(i) for i in range(len(test_pieces))
        ]
        mock_rep_returns = [
            'IndP-{} no pairs'.format(i) for i in range(len(test_pieces))
        ]
        mock_rep.side_effect = lambda *x: mock_rep_returns.pop(0)
        expected = [
            'IndP-{} no pairs'.format(i) for i in range(len(test_pieces))
        ]
        exp_analyzers = [noterest.NoteRestIndexer, interval.IntervalIndexer]
        exp_mock_guc = [mock.call(i) for i in range(len(test_pieces))]

        test_wc = WorkflowManager(test_pieces)
        test_wc.settings(None, 'include rests', True)
        test_wc.settings(None, 'count frequency', False)
        test_wc.settings(None, 'voice combinations', voice_combos)
        actual = test_wc._intervs()  # pylint: disable=protected-access

        self.assertSequenceEqual(exp_mock_guc, mock_guc.call_args_list)
        self.assertEqual(len(test_pieces), len(expected), len(actual))
        self.assertEqual(0, mock_rfa.call_count)
        self.assertEqual(len(test_pieces), mock_rep.call_count)
        for i in range(len(test_pieces)):
            mock_rep.assert_any_call(exp_into_mock_rep[i], exp_voice_combos)
        for piece in test_pieces:
            piece.get_data.assert_called_once_with(exp_analyzers,
                                                   test_settings)
        for i in range(len(actual)):
            self.assertSequenceEqual(expected[i], actual[i])
예제 #7
0
def import_files(request):
    """
    Called with the /api/import URL to load files into the WorkflowManager and return the metadata
    it discovers.
    """
    filepaths = [
        piece.file.path
        for piece in Piece.objects.filter(user_id=request.session.session_key)
    ]
    workm = WorkflowManager(filepaths)
    workm.load('pieces')
    request.session['workm'] = workm
    return [{
        "Filename": os.path.basename(workm.metadata(i, 'pathname')),
        "Title": workm.metadata(i, 'title'),
        "Part Names": workm.metadata(i, 'parts'),
        "Offset": None,
        "Part Combinations": None,
        "Repeat Identical": False
    } for i in xrange(len(workm))], 200
예제 #8
0
    def test_intervals_6(self):  # TODO: add a frequency-counted test
        """test Soprano and Alto of bwv77; with quality; not counting frequency"""
        # NB: the "expected" was hand-counted
        expected = pandas.read_csv(os.path.join(VIS_PATH, 'tests', 'expecteds',
                                                'bwv77', 'SA_intervals.csv'),
                                   comment='#',
                                   index_col=0,
                                   header=[0, 1],
                                   quotechar="'")

        test_wm = WorkflowManager(
            [os.path.join(VIS_PATH, 'tests', 'corpus', 'bwv77.mxl')])
        test_wm.load('pieces')
        test_wm.settings(0, 'voice combinations', '[[0, 1]]')
        test_wm.settings(None, 'count frequency', False)
        test_wm.settings(None, 'interval quality', True)
        actual = test_wm.run('intervals')

        self.assertEqual(1, len(actual))
        actual = actual[0].dropna()
        self.assertDataFramesEqual(expected, actual)
예제 #9
0
 def test_intervals_5(self):
     """test all combinations of vis_Test_Piece"""
     test_wm = WorkflowManager(
         [os.path.join(VIS_PATH, 'tests', 'corpus', 'vis_Test_Piece.xml')])
     test_wm.load('pieces')
     test_wm.settings(0, 'voice combinations', 'all pairs')
     test_wm.settings(None, 'include rests', True)
     expected = pandas.read_csv(os.path.join(VIS_PATH, 'tests', 'corpus',
                                             'test_intervals_5.csv'),
                                index_col=0)
     actual = test_wm.run('intervals')
     self.assertEqual(1, len(actual.columns))
     self.assertSequenceEqual(list(expected.columns), list(actual.columns))
     for col_name in expected.columns:
         self.assertEqual(len(expected[col_name]), len(actual[col_name]))
         for each_interval in expected[col_name].index:
             # NOTE: for whatever reason, the "expected" file always imports with an Int64Index,
             #       so .loc() won't find things properly unless we give the int64 index to the
             #       expected and the str index to the actual
             self.assertEqual(expected[col_name].loc[each_interval],
                              actual[col_name].loc[str(each_interval)])
예제 #10
0
    def setData(self, index, value, role):
        """
        Set the data for the piece and metadatum or setting specified. If the internal
            :class:`WorkflowManager` has not yet been created and this is the last pathname added,
            instantiate the :class:`WorkflowManager` and call :meth:`load`.

        :param index: The row-and-column index you wish to access. Either you can use a
            :class:`QModelIndex` or a 2-tuple where the first element is an ``int`` representing the
            index of the piece in the models, and the second element is one of the class properties
            described above in "Columns in the Data Model."
        :type index: :class:`QModelIndex` or 2-tuple of ``int``

        :param value: The desired value of the setting or metadatum. If you submit a
            :class:`QVariant`, we will call :meth:`toPyObject` before sending to the
            :class:`WorkflowManager`.
        :type value: :class:`QVariant` or any

        :param role: This should be Qt.EditRole.
        :type role: :class:`EditRole`

        :returns: Whether the data was successfully set.
        :rtype: ``True`` or ``False``

        .. note:: If the internal :class:`WorkflowManager` has not been instantiated, you can only
            set the ``pathname`` field. All other calls to :meth:`setData` will fail.
        """

        if Qt.EditRole != role:
            return False

        # Set the row and column
        row = None
        column = None
        if isinstance(index, QModelIndex):
            # if the QModelIndex is invalid, we won't bother with it
            if not index.isValid():
                return False
            # otherwise, get the row and column from the QModelIndex
            row = index.row()
            column = index.column()
        else:
            row = index[0]
            column = index[1]
            index = self.createIndex(row, column)

        # Verify the row and column
        if row >= self.rowCount() or column >= self._num_cols and \
        (column != WorkflowWrapper.quality and column != WorkflowWrapper.simple_ints):
            return False

        set_val = value.toPyObject() if isinstance(value, QVariant) else value

        # ensure we're trying to set a valid thing
        if self._workm is None:
            if WorkflowWrapper.filename != column:
                return False
            else:
                self._pathnames[row] = set_val
                ch_ind_1, ch_ind_2 = None, None
                if all(self._pathnames):
                    self._workm = WorkflowManager(self._pathnames)
                    self._workm.load(u'pieces')
                    # now that we imported, all the data's changed
                    ch_ind_1 = self.createIndex(0, 0)
                    ch_ind_2 = self.createIndex(len(self), self._num_cols - 1)
                    # let the GUI know
                    self._when_done_import()
                else:
                    # only one cell has changed
                    ch_ind_1 = ch_ind_2 = self.createIndex(row, column)
                self.dataChanged.emit(ch_ind_1, ch_ind_2)
                return True

        # displayed fields
        if WorkflowWrapper.filename == column:
            self._workm.metadata(row, u'pathname', set_val)
        elif WorkflowWrapper.title == column:
            self._workm.metadata(row, u'title', set_val)
        elif WorkflowWrapper.parts_list == column:
            self._workm.metadata(row, u'parts', set_val)
        elif WorkflowWrapper.offset_interval == column:
            self._workm.settings(row, u'offset interval', set_val)
        elif WorkflowWrapper.parts_combinations == column:
            self._workm.settings(row, u'voice combinations', set_val)
        elif WorkflowWrapper.repeat_identical == column:
            # the wording in the GUI and WorkflowManager has opposite meanings
            self._workm.settings(row, u'filter repeats', not set_val)
        # non-displayed fields
        elif WorkflowWrapper.quality == column:
            self._workm.settings(None, u'interval quality', set_val)
        elif WorkflowWrapper.simple_ints == column:
            self._workm.settings(None, u'simple intervals', set_val)
        else:
            return False
        self._settings_changed = True
        self.dataChanged.emit(index, index)
        return True