def _two_part_modules(self, index): """ Prepare a list of frequencies of two-part interval n-grams in a piece. This method is called by :meth:`_interval_ngrams` when required. These indexers and experimenters will run: * :class:`~vis.analyzers.indexers.interval.IntervalIndexer` * :class:`~vis.analyzers.indexers.interval.HorizontalIntervalIndexer` * :class:`~vis.analyzers.indexers.ngram.NGramIndexer` :param index: The index of the IndexedPiece on which to the experiment, as stored in ``self._data``. :type index: int :returns: The result of :class:`NGramIndexer` for a single piece. :rtype: list of :class:`pandas.Series` """ piece = self._data[index] # make settings for interval indexers settings = {u'quality': self.settings(index, u'interval quality')} settings[u'simple or compound'] = u'simple' if self.settings(None, u'simple intervals') \ is True else u'compound' vert_ints = piece.get_data([noterest.NoteRestIndexer, interval.IntervalIndexer], settings) horiz_ints = piece.get_data([noterest.NoteRestIndexer, interval.HorizontalIntervalIndexer], settings) # run the offset and repeat indexers, if required vert_ints = self._run_off_rep(index, vert_ints) horiz_ints = self._run_off_rep(index, horiz_ints) # each key in vert_ints corresponds to a two-voice combination we should use post = [] for combo in vert_ints.iterkeys(): # which "horiz" part to use? horiz_i = interval.key_to_tuple(combo)[1] # make the list of parts parts = [vert_ints[combo], horiz_ints[horiz_i]] # assemble settings setts = {u'vertical': [0], u'horizontal': [1]} setts[u'mark singles'] = self.settings(None, u'mark singles') setts[u'continuer'] = self.settings(None, u'continuer') setts[u'n'] = self.settings(None, u'n') if self.settings(None, u'include rests') is not True: setts[u'terminator'] = u'Rest' # run NGramIndexer, then append the result to the corresponding index of the dict post.append(piece.get_data([ngram.NGramIndexer], setts, parts)[0]) return post
def test_two_part_modules_1(self, mock_int, mock_nri, mock_ng, mock_horiz, mock_ror): # - we'll only use self._data[1]; excluding "Rest" # 1.) prepare the test and mocks test_pieces = [MagicMock(IndexedPiece, name=x) for x in [u'test1', u'test2', u'test3']] # set up fake part names for piece in test_pieces: piece.metadata.return_value = [u'S', u'A', u'T', u'B'] # set up pseudo-IntervalIndexer results for mock_ror part_combos = [u'0,3', u'1,3', u'2,3', u'0,1', u'0,2', u'1,2'] ror_vert_ret = {x: MagicMock(name=u'piece2 part ' + x) for x in part_combos} ror_horiz_ret = [MagicMock(name=u'piece2 horiz ' + str(x)) for x in xrange(4)] ror_returns = [ror_vert_ret, ror_horiz_ret] def ror_side_effect(*args, **kwargs): # NB: we need to accept "args" as a mock framework formality # pylint: disable=W0613 return ror_returns.pop(0) mock_ror.side_effect = ror_side_effect # set up fake return values for IntervalIndexer vert_ret = u"IntervalIndexer's return" horiz_ret = u"HorizontalIntervalIndexer's return" # set up return values for IndexedPiece.get_data() returns = [vert_ret, horiz_ret, [u'piece2 3rd get_data()'], [u'piece2 4th get_data()'], [u'piece2 5th get_data()'], [u'piece2 6th get_data()'], [u'piece2 7th get_data()'], [u'piece2 8th get_data()']] def side_effect(*args): # NB: we need to accept "args" as a mock framework formality # pylint: disable=W0613 return returns.pop(0) for piece in test_pieces: piece.get_data.side_effect = side_effect expected = [x[0] for x in returns[2:]] # 2.) prepare WorkflowManager and run the test test_wc = WorkflowManager(test_pieces) test_index = 1 test_wc.settings(test_index, u'interval quality', True) test_wc.settings(test_index, u'simple intervals', True) test_wc.settings(test_index, u'filter repeats', False) test_wc.settings(test_index, u'offset interval', None) actual = test_wc._two_part_modules(test_index) # 3.) confirm everything was called in the right order # - that every IP is asked for its vertical and horizontal interval indexes # (that "mark singles" and "continuer" weren't put in the settings) expected_interv_setts = {u'quality': True, u'simple or compound': u'simple'} expected_ngram_settings = {u'horizontal': [1], u'vertical': [0], u'n': 2, u'continuer': 'dynamic quality', u'mark singles': False, u'terminator': u'Rest'} # four-part piece means 6 combinations for NGramIndexer, plus 2 calls to interval indexers self.assertEqual(8, test_pieces[test_index].get_data.call_count) exp_calls = [mock.call([mock_nri, mock_int], expected_interv_setts), mock.call([mock_nri, mock_horiz], expected_interv_setts)] for i in xrange(len(exp_calls)): self.assertEqual(test_pieces[test_index].get_data.mock_calls[i], exp_calls[i]) # - that _run_off_rep() is called once for horizontal and vertical self.assertEqual(2, mock_ror.call_count) mock_ror.assert_any_call(test_index, vert_ret) mock_ror.assert_any_call(test_index, horiz_ret, is_horizontal=True) # - that each IndP.get_data() called NGramIndexer with the right settings at some point for combo in ror_vert_ret.iterkeys(): test_pieces[1].get_data.assert_any_call([mock_ng], expected_ngram_settings, [ror_vert_ret[combo], ror_horiz_ret[interval.key_to_tuple(combo)[1]]]) self.assertSequenceEqual(expected, actual)
def test_key_to_tuple_2(self): in_val = u'234522,98100' expected = (234522, 98100) actual = key_to_tuple(in_val) self.assertSequenceEqual(expected, actual)
def test_key_to_tuple_1(self): in_val = u'5,6' expected = (5, 6) actual = key_to_tuple(in_val) self.assertSequenceEqual(expected, actual)