Tutorial: Use the WorkflowManager¶
The script developed in Tutorial: Use N-Grams to Find Melodic Patterns is suitable for users doing exploratory work in an interactive Python shell.
When a query becomes regularized and you want it to be easily repeatable, or if you are an application developer making a graphical interface (whether on the Web or in a desktop application) you can take advantage of a further layer of abstraction offered by our WorkflowManager
.
The WorkflowManager
is designed as the point of interaction for end-user applications, providing a consistent interface and reference implementations of the steps involved in all queries.
While every new query will involve modifying a portion of the run()
method’s code, you may be able to re-use the existing input and output methods without change.
The WorkflowManager
‘s documentation describes its functionality:
-
class
vis.workflow.
WorkflowManager
(pathnames)[source] Warning: The WorkflowManager is deprecated as of VIS 3.0 and will be entirely removed in VIS 4.0. Most of its functionality still works with VIS 3.0 but this is not guaranteed and it is no longer being supported in development.
Parameters: pathnames (list or tuple of string or IndexedPiece
) – A list of pathnames.The
WorkflowManager
automates several common music analysis patterns for counterpoint. Use theWorkflowManager
with these four tasks:load()
, to import pieces from symbolic data formats.run()
, to perform a pre-defined analysis.output()
, to output analysis results.
Before you analyze, you may wish to use these methods:
metadata()
, to get or set the metadata of a specificIndexedPiece
managed by thisWorkflowManager
.settings()
, to get or set a setting related to analysis (for example, whether to display the quality of intervals).
You may also treat a
WorkflowManager
as a container:>>> wm = WorkflowManager(['piece1.mxl', 'piece2.krn']) >>> len(wm) 2 >>> ip = wm[1] >>> type(ip) <class 'vis.models.indexed_piece.IndexedPiece'>
Port a Query into the WorkflowManager¶
Porting an existing query to the WorkflowManager
involves fitting its code into the appropriate pre-existing methods.
The load()
method prepares IndexedPiece
objects and metadata by loading files for analysis.
The output()
method outputs query results to a variety of formats, including spreadsheets, charts, and scores.
You will not usually need to modify load()
, and you may not need to modify output()
either.
The majority of development work will be spent in the run()
method or its related hidden methods (like the _intervs()
, _inteval_ngrams()
, and other methods that are included in the default WorkflowManager
).
TODO: continue revising here.
When I add my new query’s logic to the run()
method, I get this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | def run(self):
ngram_settings = {'vertical': [0], 'n': self.settigns(None, 'n')}
ngram_freqs = []
for i, piece in enumerate(self._data):
interval_settings = {'quality': self.settings(i, 'interval quality')}
intervals = piece.get_data( \
[noterest.NoteRestIndexer, interval.HorizontalIntervalIndexer], \
interval_settings)
for part in intervals:
ngram_freqs.append( \
piece.get_data([ngram.NGramIndexer, frequency.FrequencyExperimenter], \
ngram_settings, \
[part]))
agg_p = AggregatedPieces(ind_ps)
self._result = agg_p.get_data([aggregator.ColumnAggregator], [], {}, ngram_freqs)
|
I made the following changes:
- Remove the
instruction
parameter fromrun()
, since there is only one experiment. - Use the
import
statements at the top of the file. - Use
self._data
rather than building my own list ofIndexedPiece
objects (inenumerate()
on line 5). - Set
interval_settings
per-piece, and use the value from built-inWorkflowManager
settings. - Set
n
from the built-inWorkflowManager
settings.
I could also use the WorkflowManager.settings()
method to get other settings by piece or shared across all pieces, like 'simple intervals'
, which tells the HorizontalIntervalIndexer
whether to display all intervals as their single-octave equivalents.
To run the same analysis as in Tutorial: Use N-Grams to Find Melodic Patterns, use the WorkflowManager
like this:
1 2 3 4 5 6 7 8 9 | from vis.workflow import WorkflowManager
pathnames = [list_of_pathnames]
work = WorkflowManager(pathnames)
work.load('pieces')
for i in xrange(len(work)):
work.settings(i, 'quality', True)
work.run()
work.export('CSV', 'output_filename.csv')
|
This script actually does more than the program in Tutorial: Use N-Grams to Find Melodic Patterns because export()
“converts” the results to a DataFrame
, sorts, and outputs the results.