Package: prosodic
ProsodicProsodic is a metrical-phonological parser written in Python. Currently, it can parse English and Finnish text, but adding additional languages is easy with a pronunciation dictionary or a custom python function. Prosodic was built byRyan Heuser,Josh Falk, andArto Anttila, beginning in the summer of 2010. Josh also maintainsanother repository, in which he has rewritten the part of this project that does phonetic transcription for English and Finnish.Sam Bowmanhas contributed to the codebase as well, adding several new metrical constraints.About ProsodicProsodic does two main things. First, it tokenizes text into words, and then converts each word into its stressed, syllabified, phonetic transcription. Second, if desired, it finds the best available metrical parse for each line of text. In the style of Optimality Theory, (almost) all logically possible parses are attempted, but the best parses are those that least violate a set of user-defined constraints. The default metrical constraints are those proposed by Kiparsky and Hanson in their paper "A Parametric Theory of Poetic Meter" (Language, 1996). See below for how these and other constraints are implemented.Example of metrical parsingHere's an example of the metrical parser in action, on Shakespeare's first sonnet.[text]                                    				[parse]                                   
from fairest creatures we desire increase				from|FAI|rest|CREA|tures|WE|de|SIRE|in|CREASE
that thereby beauty's rose might never die				that|THERE|by|BEAU|ty's|ROSE|might|NEV|er|DIE
but as the riper should by time decease 				but|AS|the|RI|per|SHOULD|by|TIME|de|CEASE
his tender heir might bear his memory   				his|TEN|der|HEIR|might|BEAR|his|MEM|o|RY
but thou contracted to thine own bright eyes			but|THOU|con|TRACT|ed|TO|thine|OWN|bright|EYES
feed'st thy light's flame with self substantial fuel	FEED'ST|thy|LIGHT'S|flame.with|SELF|sub|STAN|tial|FU|el
making a famine where abundance lies    				MAK|ing.a|FA|mine|WHERE|ab|UN|dance|LIES
thy self thy foe to thy sweet self too cruel			thy|SELF|thy|FOE|to.thy|SWEET.SELF|too|CRU|el
thou that art now the world's fresh ornament			thou|THAT|art|NOW|the|WORLD'S|fresh|OR|na|MENT
and only herald to the gaudy spring     				and|ON|ly|HER|ald|TO|the|GAU|dy|SPRING  
within thine own bud buriest thy content				with|IN|thine|OWN|bud|BU|ri|EST|thy|CON|tent
and tender churl mak'st waste in niggarding				and|TEN|der|CHURL|mak'st|WASTE|in|NIG|gard|ING
pity the world or else this glutton be  				PI|ty.the|WORLD|or|ELSE|this|GLUT|ton|BE
to eat the world's due by the grave and thee			to|EAT|the|WORLD'S|due|BY|the|GRAVE|and|THEENot bad, right? Prosodic not only captures the sonnet's overall iambic meter, but also some of its variations. It accurately captures the trochaic inversions in the lines "Making afaminewhereabundancelies" and "Pity theworldorelsethisgluttonbe." Also, depending on the constraints, it also captures the double-strong beat that can often follow a double-weak beat in the line "Thyselfthyfoeto thysweet selftoocruel" (see, for this metrical pattern,Bruce Hayes' review of Derek Attridge'sThe Rhythms of English PoetryinLanguage60.1, 1984). It also gets some lines wrong: its interpretation of "feed'st thy light's flame," for example. But how accurate is it on average?Metrical annotation outputSeeherefor a quick look at the three output statistics, files are produced in the metrical annotation process.Accuracy of metrical parserIn preliminary tests, we ran Prosodic against a sample of 1800 hand-parsed lines of iambic, trochaic, anapestic, and dactylic verse (included). For example, here is a line, and how it was parsed by a human, Prosodic, and the "bare template" of its poem's meter (iambic).Line:       Anxious  in  vain  to  find  the  distant  floor

Human:      ANxious  in  VAIN  to  FIND  the  DIStant  FLOOR
            s   w    w   s     w   s     w    s  w     s

Prosodic:   ANxious  in  VAIN  to  FIND  the  DIStant  FLOOR
            s   w    w   s     w   s     w    s  w     s

Template:   anXIOUS  in  VAIN  to  FIND  the  DIStant  FLOOR
            w   s    w   s     w   s     w    s  w     s
            *   *We can see that Prosodic gets this line right; the template gets most of it right, missing only the trochaic inversion. By running all of the lines through in this way (using the/evalcommand of Prosodic [see below]) we can see what percentage of syllables both Prosodic and a template "correctly" capture—where "correct" is to agree with the human parse.% Syllables Correctly ParsedAnother HumanProsodicBase Template (for this meter)Base Template (iambic meter)Iambic lines93.7%92.6%89.0%89.0%Trochaic lines98.8%94.5%95.3%4.5%Anapestic lines97.2%84.7%66.1%52.9%Dactylic lines95.8%83.8%75.6%49.7%The extent to which two human taggers (both English literature Ph.D. students) agree is in the first column: given that metrical scansion inevitably varies from person to person, this might be taken as the upper threshold of what we could expect Prosodic to do. But Prosodic is not too far off, especially for the binary meters (iambic and trochaic). The ternary meters are more complicated: they depart more often from their metrical templates, as can be seen in the third column. But the third column of metrical templates assumes that we already know the meter of the poem (which, in this evaluation sample, we do). Not surprisingly, if we don't already know the meter, and simply apply an iambic template to every poem, then it works well for iambic poems, but not at all for poems of other meters—as can be seen in the fourth column. This means thatfor parsing poems whose meter is unknown, or for parsing free verse poems or even prose, Prosodic is especially useful. Parsing lines individually, and agnostic as to the meter of "the poem," Prosodic is nonetheless able to discover the basic contours of the metrical patterns in the lines. Inanother research project, run out of theStanford Literary Lab, Prosodic's parses were able to predict the overall meter in 200 poems with about 98% accuracy.The data above were produced when the meter was defined as the following constraints and weights:[*strength.s=>-u/3.0] [*strength.w=>-p/3.0] [*stress.s=>-u/2.0] [*stress.w=>-p/2.0] [*footmin-none/1.0] [*footmin-no-s-unless-preceded-by-ww/10.0] [*posthoc-no-final-ww/2.0] [*posthoc-standardize-weakpos/1.0] [*word-elision/1.0]. These and other constraints are mentioned below, but are best documented in their confuration file,config.py.[One final note: these human annotations—made by literature Ph.D. students—embody certain assumptions about meter that are common in literary, but not linguistic circles. For instance, representing a trochaic inversion as a literal inversion of feet, "swws," is not how Kiparsky would represent it; for him, a trochaic inversion is simply a conventional, permissible violation of the iambic meter. However, Prosodic doesn't necessarily commit itself to either of these theories or approaches: parses that conform to either theory can be generated using different sets of constraints.]InstallationQuick startTo install Prosodic, it's best to install using pip. In a terminal, type:pip install git+https://github.com/quadrismegistus/prosodic.gitAfter installation, you should have access to the "prosodic" executable. Simply run:prosodicto open up the interactive terminal interface.Quick start (within Python)Prosodic can also be used as a python module within your own applications:import prosodic as p
text = p.Text("Shall I compare thee to a summer's day?")
text.parse()Instructions on how to use Prosodic in interactive mode, and as a python module, are below.ExampleCheck outherefor an example of using Prosodic from within Python on Google Colab.UsageThere are two main ways of using Prosodic: in interactive mode, and, for more Python-advanced users, as a Python module.Interactive modeYou can enter the interactive mode of prosodic by runningprosodic. This will bring you to an interface like this:################################################
## welcome to prosodic!                  v1.3 ##
################################################


	[please type a line of text, or enter one of the following commands:]
		/text	load a text
		/corpus	load folder of texts
		/paste	enter multi-line text

		/eval	evaluate this meter against a hand-tagged sample
		/mute	hide output from screen
		/save	save previous output to file
		/exit	exit

>> [0.0s] prosodic:en$Loading textThe first thing to do when using Prosodic is to give it some text to work with. There are a few ways of doing this. The simplest way is to simply type in a line, one at a time. You can also type/paste, and then enter or copy/paste multiple lines at a time. You can also type/textto load a text, or/corpusto load a folder of text files. If you do, you'll be given instructions on how either to specify a relative path from within Prosodic's corpus folder, or an absolute path to another file or folder on your disk. You can also define the text you want to work with as an argument for the command you use to boot Prosodic with:prosodic /path/to/my/file.txt.Checking phonetic/phonological annotationsEven before metrically parsing the text you've loaded (see below), you can run a few commands to test out how Prosodic has interpreted the text in terms of its phonetics and phonology. The command/showwill show the phonetic transcription and stress- and weight-profiles for each word:000001  of                      P:ʌv                                S:U     W:L
000002  mans                    P:'mænz                             S:P     W:H
000003  first                   P:'fɛːst                            S:P     W:H
000004  disobedience            P:`dɪ.sə.'biː.diː.əns               S:SUPUU W:LLHHH
000005  and                     P:ænd                               S:U     W:L
000006  the                     P:ðə                                S:U     W:L
000007  fruit                   P:'fruːt                            S:P     W:HThe command/treeshows a hierarchical description of each word's phonology, as it is embedded in the hierarchical organization of the text. For instance, the beginning of the output from/treefor this line would be:-----| (S1) <Stanza>
      |
      |-----| (S1.L1) <Line>                                                                       [of mans first disobedience and the fruit]
            |
            |-----| (S1.L1.W1) <Word>	of	<ʌv>
                  |     [+functionword]
                  |     [numSyll=1]
                  |
                  |-----| (S1.L1.W1.S1) <Syllable>                                                 [ʌv]
                        |     [prom.stress=0.0]
                        |
                        |-----| (S1.L1.W1.S1.SB1) <SyllableBody>                                   [ʌv]
                              |     [shape=VC]
                              |     [-prom.vheight]
                              |     [-prom.weight]
                              |
                              |-----| (S1.L1.W1.S1.SB1.O1) <Onset>
                              |
                              |-----| (S1.L1.W1.S1.SB1.R2) <Rime>
                                    |
                                    |-----| (S1.L1.W1.S1.SB1.R2.N1) <Nucleus>
                                          |     [-prom.vheight]
                                          |
                                          |-----| (S1.L1.W1.S1.SB1.R2.N1.P1) <Phoneme>             [ʌ]
                                    |
                                    |-----| (S1.L1.W1.S1.SB1.R2.C2) <Coda>
                                          |
                                          |-----| (S1.L1.W1.S1.SB1.R2.C2.P1) <Phoneme>             [v]
            |
            |-----| (S1.L1.W2) <Word>	mans	<'mænz>
                  |     [numSyll=1]
                  |
                  |-----| (S1.L1.W2.S1) <Syllable>                                                 ['mænz]
                        |     [prom.stress=1.0]
                        |     [prom.kalevala=1.0]
                        |
                        |-----| (S1.L1.W2.S1.SB1) <SyllableBody>                                   [mænz]
                              |     [shape=CVCC]
                              |     [-prom.vheight]
                              |     [+prom.weight]
                              |
                              |-----| (S1.L1.W2.S1.SB1.O1) <Onset>
                                    |
                                    |-----| (S1.L1.W2.S1.SB1.O1.P1) <Phoneme>                      [m]
                              |
                              |-----| (S1.L1.W2.S1.SB1.R2) <Rime>
                                    |
                                    |-----| (S1.L1.W2.S1.SB1.R2.N1) <Nucleus>
                                          |     [-prom.vheight]
                                          |
                                          |-----| (S1.L1.W2.S1.SB1.R2.N1.P1) <Phoneme>             [æ]
                                    |
                                    |-----| (S1.L1.W2.S1.SB1.R2.C2) <Coda>
                                          |
                                          |-----| (S1.L1.W2.S1.SB1.R2.C2.P1) <Phoneme>             [n]
                                          |
                                          |-----| (S1.L1.W2.S1.SB1.R2.C2.P2) <Phoneme>             [z]Lastly, the/querycommand allows you to query these phonological annotations. Once/queryis entered, the query language parser starts up (type/to exit, or hitCtrl+D). Which are the stressed syllables in the text?(Syllable: [+prom.stress]). Which are all the voiced phonemes?(Phoneme: [+voice]). Which are all the syllables with voiced onsets and codas?(Syllable: (Onset: [+voice]) (Coda: [+voice])). Etc.Metrically parsing textThe command/parsewill metrically parse whatever text is currently loaded into Prosodic. Once the text is parsed, further commands become possible, all of which either view or save the data gleaned from the parser.The command/scanprints the best parse for each line, along with statistics on which constraints it violated. [This output, like any other output, can be saved to disk (and then opened with Excel) by using the/savecommand.] For instance, here are the first four lines ofParadise Lost, using the/scancommand:text                                    		parse                                   		#pars	#viol	meter			[*footmin-none]	[*strength.s=>-u]	[*strength.w=>-p]	[*stress.s=>-u]	[*stress.w=>-p]
of mans first disobedience and the fruit		of|MANS|first|DI|so|BE|di|ENCE|and.the|FRUIT	3		5		wswswswswws		0				0					2					2				1
of that forbidden tree whose mortal tast		of|THAT|for|BID|den|TREE|whose|MOR|tal|TAST		1		0		wswswswsws		0				0					0					0				0
brought death into the world and all our woe	brought|DEATH|in|TO|the|WORLD|and|ALL|our|WOE	1		2		wswswswsws		0				0					0					2				0
with loss of eden till one greater man  		with|LOSS|of|ED|en|TILL|one|GRE|ater|MAN		1		2		wswswswsws		0				0					2					0				0The command/reportis a more verbose version of/scan, printing each possible (i.e. non-harmonically-bounded) parse for each line. For instance, for each line, it produces an output like:==============================
[line #1 of 4]: of mans first disobedience and the fruit

	--------------------
	[parse #3 of 3]: 8.0 errors
	1	w	of        	
	2	s	MANS      	
	3	w	first     	[*stress.w=>-p]
	4	s	DI        	
	5	w	so        	
	6	s	BE        	
	7	w	di        	
	8	s	ENCE      	[*stress.s=>-u]
	9	w	and       	
	10	s	THE       	[*stress.s=>-u]
	11	w	fruit     	[*stress.w=>-p]

	[*stress.s=>-u]: 4.0  [*stress.w=>-p]: 4.0  
	--------------------

	--------------------
	[parse #2 of 3]: 5.0 errors
	1	w	of        	
	2	s	MANS      	
	3	w	first     	[*stress.w=>-p]
	4	s	DI        	
	5	w	so        	
	6	s	BE        	
	7	w	di ence   	[*footmin-none]
	8	s	AND       	[*stress.s=>-u]
	9	w	the       	
	10	s	FRUIT     	

	[*footmin-none]: 1.0  [*stress.s=>-u]: 2.0  [*stress.w=>-p]: 2.0  
	--------------------

	--------------------
	[parse #1 of 3]: 5.0 errors
	1	w	of        	
	2	s	MANS      	
	3	w	first     	[*stress.w=>-p]
	4	s	DI        	
	5	w	so        	
	6	s	BE        	
	7	w	di        	
	8	s	ENCE      	[*stress.s=>-u]
	9	w	and the   	[*footmin-none]
	10	s	FRUIT     	

	[*footmin-none]: 1.0  [*stress.s=>-u]: 2.0  [*stress.w=>-p]: 2.0  
	--------------------

==============================Finally, you can also save a variety of statistics from the metrical parser in tab-separated form by running the/statscommand.Evaluating the meter against a hand-parsed sampleHow well does Prosodic do when its metrical parses are compared with those that a human reader has annotated? The statistics above, in "Accuracy of metrical parser," were generated from the evaluation command:/eval. From there, you can select a spreadsheet (either a tab-separated text file or an excel document) saved in thetagged_samples/folder to use as the "ground truth", human-annotated parse. The/evalcommand will ask which columns in the file correspond to the line ("Of man's first disobedience and the fruit"), the parse ("wswswswwsws"), and (optionally) the meter of the line ("iambic"). Prosodic will then parse the lines under the "line" column (using, as always, the current configuration of metrical constraints inconfig.py), and save statistics to the same folder in tab-separated form. The spreadsheet used in the above accuracy table is provided, made by the Stanford Literary Lab'spoetry projectin 2014 and 2016.Configuration optionsAll configuration of Prosodic takes place inconfig.pyin your prosodic data folder, which is by default the folderprosodic_datain your home folder. (If onlyconfig_default.pyis there, copy that toconfig.py.) This file is fairly well documented and is the best source of documentation on how to use it. (It's best to edit this file inside a text editor that highlights the Python syntax, so you can visually see which settings are deactivated by being "commented-out," i.e. by having a "#" character at the start of their lines.) Here is a list of what you will find there.Technical options about how Prosodic works:The paths used for corpora, results, and tagged samplesThe language used (currently, English or Finnish)Which Text-to-Speech engine, if any, is used for parsing unknown English wordsWhether to print output to screenOptions about metrical parsing:The minimum and maximum size of metrical positions (from a mora to two or more syllables)The constraints used in metrical parsing, some of which are:Constraints proposed by Kiparsky and Hanson in "A Parametric Theory of Poetic Meter" (Language, 1996):Strength: A weak/strong syllable should not be in a strong/weak metrical position.Stress: An unstressed/stressed syllable should not bein a strong/weak metrical position.Weight: A light/heavy syllable should not be in a strong/weak metrical position.Minimal foot: a disyllabic metrical position should not contain more than a minimal foot (only if the syllables are weighted light-heavy or light-light is a disyllabic position allowed).Other constraints regulating disyllabic metrical positionsConstraints allowing the initial parts of lines to be extrametricalConstraints regulating word elisions (e.g. "Plu-ton-i-an" becoming "Plu-ton-ian")What to pass to the metrical parser: a line in the text file, a line between punctuation markers, etc.Options about words and tokenization:The regular expression used for word tokenizationFor words with multiple stress profiles (e.g. "INto" and "inTO"), whether to allow the metrical parser to choose the stress profile based on whichever works best metrically in the lineWhether to allow elided pronunciations (e.g. "Plu-ton-ian" for "Plu-ton-i-an") as metrical possibilities alsoHow to display the phonetic output for words (IPA, orthography, CMU notation)Again, please see the documentation withinconfig.pyfor more information.Running Prosodic as a python moduleProsodic can also be run within other python applications.In [1]: import prosodic as p

In [2]: t = p.Text("corpora/shakespeare/sonnet-001.txt")

In [3]: t.parse()

In [4]: for parse in t.bestParses():
   ...:     print parse
   ...:     
from|FAI|rest|CREA|tures|WE|de|SIRE|in|CREASE
that|THERE|by|BEAU|ty's|ROSE|might|NEV|er|DIE
[...]For more information on this, please seethe Wiki.DependenciesText to speech engine for parsing unknown English wordsBy default, Prosodic uses the CMU pronunciation dictionary to discover the syllable boundaries, stress pattern, and other information about English words necessary for metrical parsing. Lines with words not in this dictionary are, again by default, skipped when parsing. However, with a Text-to-Speech engine, it's possible to "sound out" unknown English words into a stressed, syllabified form that can then be parsed. Prosodic supports two TTS engines:espeak(recommended), andOpenMary. I find that espeak produces better syllabifications than OpenMary (at least for English), and is simpler to use, but either will work just fine.Setting up espeakEspeakis an open-source TTS engine for Windows and Unix systems (including Mac OS X). You candownload it for your operating system here. But if you're running Mac OS X, an even simpler way to install espeak is via theHomeBrew package manager. To do so, install homebrew if you haven't, and then run in a terminal:brew install espeak. After you've installed espeak, set the "en_TTS_ENGINE" flag in theconfig.pyfile to "espeak." That's it!Note:Espeak producesun-syllabified IPA transcriptions of any given (real or unreal) word. To syllabify these, thesyllabifierfrom thePenn Phonetics Toolkit (P2TK)is used. An extra plus from this pipeline is consistency: this same syllabifier is responsible for the syllable boundaries in the CMU pronunciation dictionary, which Prosodic draws from (if possible) before resorting to a TTS engine.Setting up OpenMaryOpenMary is another open-source TTS engine, written in Java and developed by two German research institutes: theDFKI'sLanguage Technology LabandSaarland University'sInstitute of Phonetics. To install OpenMary, firstdownload it here[select the "Run time package" link]. Then, unzip the zip file, go into the unzipped folder, and start OpenMary as a server. To do that, type into the terminal after unzipping:./marytts-5.2/bin/marytts-server.sh. To use OpenMary in Prosodic, you'll have to make sure OpenMary is running as a server process beforehand; if not, you'll have to repeat the last command. For espeak, this step isn't necessary.Python module dependenciesBy default, Prosodic has no module dependencies. The modules it does use—lexconvert,P2TK'ssyllabify.py, and apython hyphenator for syllabifying English orthography—are small, and already included in the repository. However, there are a few exceptions, depending on what you want to do. To install these modules, firstinstall pipif you haven't yet.If you'd like to use the built-in query language (available under "/query" in the interactive mode), you'll need to install pyparsing:pip install pyparsing.If you're running OpenMary, you'll need to install the xml parser Beautiful Soup 4, and the unicode module unidecode:pip install bs4andpip install unidecode.If you'd like to be able to read evaluation data in spreadsheet form (*.xls, *.xlsx) (available under "/eval" in interactive mode), you'll need to install xlrd:pip install xlrd.How it worksHow does Prosodic work? Here is an overview of its two major aspects: how words are tokenized, phonetically transcribed, syllabified, and stressed; and then how that information is used to find the optimal metrical parse according to a set of constraints.From text, to words, to phonetics and phonologyProsodic first encounters a piece of English or Finnish text. It tokenizes that text according to a user-defined tokenizer, set under the option "tokenizer" inconfig.py, defaulting to splitting lines into words by whitespace and hyphens. In Finnish text, a pure-Python implementation of Finnish IPA-transcription and syllabification is provided, built by Josh Falk. In English, the process is more complicated. If the word is found in theCMU pronunciation dictionary, its syllabified, stressed, phonetic transcription is used. If not, a text-to-speech engine is used to "sound out" the unknown word, and then a syllabifier is used to break the stressed IPA transcription into syllables. For details on which text-to-speech engine and syllabifier are used, see above, "Text to speech engine for parsing unknown English words."With these phonetic-phonological transcriptions, Prosodic builds each word as a hierarchy of its constituent parts. For instance, the English word "love" is interpreted:| (W1) <Word>	love	<'l ah v>
|     [numSyll=1]
|
|-----| (W1.S1) <Syllable>                               
      |     [prom.stress=1.0]
      |
      |-----| (W1.S1.SB1) <SyllableBody>
            |     [shape=CVC]
            |     [+prom.weight]
            |
            |-----| (W1.S1.SB1.O1) <Onset>
                  |
                  |-----| (W1.S1.SB1.O1.P1) <Phoneme>          [l]
            |
            |-----| (W1.S1.SB1.R2) <Rime>
                  |
                  |-----| (W1.S1.SB1.R2.N1) <Nucleus>
                        |
                        |-----| (W1.S1.SB1.R2.N1.P1) <Phoneme> [ʌ]
                  |
                  |-----| (W1.S1.SB1.R2.C2) <Coda>
                        |
                        |-----| (W1.S1.SB1.R2.C2.P1) <Phoneme> [v]Due to this hierarchical organization, sophisticated queries become possible on the linguistic structures in their interrelationships. In other words, since the hierarchy defines basic "child-of" or "contained-in" relationships between linguistic structures, it is possible to query for, say, "all onsetswithat least one voiced consonantinstressed syllables." (For more details on the included query language, see above).From phonology to metricsOnce these phonetic and phonological annotations on words are in place, metrical parsing can then use them as it tries to maximize the correspondence between metrically strong positions and, say, syllable stress. The parsing is performed in the spirit of Optimality Theory: (almost) all logically possibile parses are attempted, but the best parses are those that least violate a set of user-defined constraints. If Parse A's total violation score is, for each constraint, the same as Parse B's, but there is at least one constraint where Parse A's violation score is even worse than Parse B's—then parse A is "harmonically bounded" by parse B. Parse A is never better than Parse B; and in at least one instance, it's worse. No matter how the constraints are weighted, these "bounded" parses are categorically worse than others. The metrical parser, written primarily byJosh Falk, works as fast as it does by disregarding harmonically bounded parses as it goes: this way, it doesn't have to travel further down a parse once it realizes that that parse has already been bounded by other parses.The number ofunboundedparses for a given line then represents something about the metrical complexity of the line. For instance, take (Shakespeare's) Richard III's line, "A horse! A horse! My kingdom for a horse!" Only one parse survives the harmonic bounding process:[parse #1 of 1]: 2.0 errors
1	w	a         	
2	s	HORSE     	
3	w	a         	
4	s	HORSE     	
5	w	my        	
6	s	KING      	
7	w	dom       	
8	s	FOR       	[*stress.s=>-u]
9	w	a         	
10	s	HORSE     	

[*stress.s=>-u]: 2.0This parse only violates one constraint: it elevated an unstressed word, "for," to a metrically strong position. Compare this line to another of Shakespeare's, which has the same number of syllables, but is metrically more complex: "Never came poison from so sweet a place." Here, four parses survive:--------------------
[parse #4 of 4]: 14.0 errors
1	w	nev       	[*strength.w=>-p][*stress.w=>-p]
2	s	ER        	[*strength.s=>-u][*stress.s=>-u]
3	w	came      	[*stress.w=>-p]
4	s	POI       	
5	w	son       	
6	s	FROM      	[*stress.s=>-u]
7	w	so        	
8	s	SWEET     	
9	w	a         	
10	s	PLACE     	

[*strength.s=>-u]: 3.0  [*strength.w=>-p]: 3.0  [*stress.s=>-u]: 4.0  [*stress.w=>-p]: 4.0  
--------------------

--------------------
[parse #3 of 4]: 13.0 errors
1	s	NEV       	
2	w	er        	
3	s	CAME POI  	[*footmin-none][*footmin-no-s-unless-preceded-by-ww]
4	w	son       	
5	s	FROM      	[*stress.s=>-u]
6	w	so        	
7	s	SWEET     	
8	w	a         	
9	s	PLACE     	

[*footmin-no-s-unless-preceded-by-ww]: 10.0  [*footmin-none]: 1.0  [*stress.s=>-u]: 2.0  
--------------------

--------------------
[parse #2 of 4]: 9.0 errors
1	s	NEV       	
2	w	er came   	[*stress.w=>-p][*footmin-none]
3	s	POI       	
4	w	son from  	[*footmin-none]
5	s	SO        	[*stress.s=>-u]
6	w	sweet a   	[*stress.w=>-p][*footmin-none]
7	s	PLACE     	

[*footmin-none]: 3.0  [*stress.s=>-u]: 2.0  [*stress.w=>-p]: 4.0  
--------------------

--------------------
[parse #1 of 4]: 6.0 errors
1	s	NEV       	
2	w	er came   	[*stress.w=>-p][*footmin-none]
3	s	POI       	
4	w	son       	
5	s	FROM      	[*stress.s=>-u]
6	w	so        	
7	s	SWEET     	
8	w	a         	
9	s	PLACE     	[*posthoc-standardize-weakpos]

[*footmin-none]: 1.0  [*posthoc-standardize-weakpos]: 1.0  [*stress.s=>-u]: 2.0  [*stress.w=>-p]: 2.0  
--------------------The best parse (at the bottom) is iambic with a trochaic inversion; it violates the constraint against demoting stressed syllables ("came") into a metrically weak position, as well as a constraint discouraging disyllabic positions. The next best is a dactylic interpretation of the line, but it too violates certain constraints. The third best tried to squeeze two syllables into a strong position, and the last—the traditional iambic parse—tried to alter the stress contour of "never," which violates constraints encouraging the correspondence between the meter and syllable "strength" in polysyllabic words.The default metrical constraints are those proposed by Kiparsky and Hanson in their paper "A Parametric Theory of Poetic Meter" (Language, 1996). Seeconfig.pyfor a better description of these and other constraints.Extending ProsodicAdding languagesThere are two possible methods by which Prosodic can understand a language:using a dictionary in the format:{word-token}[tab]{stressed, syllabified, IPA format}eg:befuddle [tab] bɪ.'fə.dəlbefuddled	[tab] bɪ.'fə.dəldbefuddles	[tab] bɪ.'fə.dəlzusing a python function which takes in a word-token as an input, and a stressed, syllabified, IPA format as its output.Currently, Finnish is implemented by the latter method; English, by a combination of two, using the dictionary for recognized words, and a python function for unrecognized words.To add entries to a language's dictionary, simply add an entry in the above format to the dictionary[language_name].tsvunder the folder[prosodic_dir]/dicts/[language_twoletter_code].To add a new language entirely, you can create a new dictionary in the above format and place it under[prosodic_dir]/dicts/[language_twoletter_code]/[language_name].tsv. Or, you can create a python file under[prosodic_dir]/dicts/[language_twoletter_code]/[language_name].py, which has a functionget(token,config={}). This function must accept a word-token as its only argument, and Prosodic's configuration settings as an optional keyword argument, and it must return a list of tuples in the form:[
	(
		<ipa unicode string>,
		<token string split into a list of syllable strings>,
		{a dictionary of optional keyword arguments to be stored on the word object},
	),
	...
]For example,get("into", config={'add_elided_pronunciations':1})might return:[
	(u"ɪn.'tuː", ['in','to'], {'is_elision': False}),
	u"'ɪn.tuː", ['in','to'], {'is_elision': False}),
	u"ɪn.tʌ", ['in','to'], {'is_elision': False})
]See theget()function indicts/en/english.pyordicts/fi/finnish.pyfor examples.Contributing to the code basePlease feel free to pull and push back to the codebase here! And feel free to use this code in your projects: it is licensed byGPLv3.