nltk 3.2__zip → 3.3__zip
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {nltk-3.2 → nltk-3.3}/INSTALL.txt +6 -6
- {nltk-3.2 → nltk-3.3}/LICENSE.txt +13 -13
- {nltk-3.2 → nltk-3.3}/MANIFEST.in +6 -6
- {nltk-3.2/nltk.egg-info → nltk-3.3}/PKG-INFO +13 -5
- nltk-3.2/README.txt → nltk-3.3/README.md +49 -48
- nltk-3.3/nltk/VERSION +1 -0
- {nltk-3.2 → nltk-3.3}/nltk/__init__.py +185 -185
- {nltk-3.2 → nltk-3.3}/nltk/app/__init__.py +52 -53
- {nltk-3.2 → nltk-3.3}/nltk/app/chartparser_app.py +2276 -2276
- {nltk-3.2 → nltk-3.3}/nltk/app/chunkparser_app.py +1262 -1264
- {nltk-3.2 → nltk-3.3}/nltk/app/collocations_app.py +347 -350
- {nltk-3.2 → nltk-3.3}/nltk/app/concordance_app.py +568 -570
- {nltk-3.2 → nltk-3.3}/nltk/app/nemo_app.py +156 -155
- {nltk-3.2 → nltk-3.3}/nltk/app/rdparser_app.py +892 -894
- {nltk-3.2 → nltk-3.3}/nltk/app/srparser_app.py +809 -809
- {nltk-3.2 → nltk-3.3}/nltk/app/wordfreq_app.py +32 -32
- {nltk-3.2 → nltk-3.3}/nltk/app/wordnet_app.py +968 -968
- {nltk-3.2 → nltk-3.3}/nltk/book.py +91 -90
- {nltk-3.2 → nltk-3.3}/nltk/ccg/__init__.py +22 -22
- {nltk-3.2 → nltk-3.3}/nltk/ccg/api.py +359 -335
- {nltk-3.2 → nltk-3.3}/nltk/ccg/chart.py +394 -361
- {nltk-3.2 → nltk-3.3}/nltk/ccg/combinator.py +343 -312
- {nltk-3.2 → nltk-3.3}/nltk/ccg/lexicon.py +328 -290
- nltk-3.3/nltk/ccg/logic.py +46 -0
- {nltk-3.2 → nltk-3.3}/nltk/chat/__init__.py +49 -49
- {nltk-3.2 → nltk-3.3}/nltk/chat/eliza.py +244 -244
- {nltk-3.2 → nltk-3.3}/nltk/chat/iesha.py +140 -140
- {nltk-3.2 → nltk-3.3}/nltk/chat/rude.py +92 -92
- {nltk-3.2 → nltk-3.3}/nltk/chat/suntsu.py +117 -117
- {nltk-3.2 → nltk-3.3}/nltk/chat/util.py +122 -120
- {nltk-3.2 → nltk-3.3}/nltk/chat/zen.py +282 -282
- {nltk-3.2 → nltk-3.3}/nltk/chunk/__init__.py +190 -190
- {nltk-3.2 → nltk-3.3}/nltk/chunk/api.py +51 -51
- {nltk-3.2 → nltk-3.3}/nltk/chunk/named_entity.py +331 -331
- {nltk-3.2 → nltk-3.3}/nltk/chunk/regexp.py +1390 -1384
- {nltk-3.2 → nltk-3.3}/nltk/chunk/util.py +600 -600
- {nltk-3.2 → nltk-3.3}/nltk/classify/__init__.py +98 -98
- {nltk-3.2 → nltk-3.3}/nltk/classify/api.py +193 -193
- {nltk-3.2 → nltk-3.3}/nltk/classify/decisiontree.py +295 -295
- {nltk-3.2 → nltk-3.3}/nltk/classify/maxent.py +1510 -1492
- {nltk-3.2 → nltk-3.3}/nltk/classify/megam.py +179 -178
- {nltk-3.2 → nltk-3.3}/nltk/classify/naivebayes.py +245 -242
- {nltk-3.2 → nltk-3.3}/nltk/classify/positivenaivebayes.py +170 -170
- {nltk-3.2 → nltk-3.3}/nltk/classify/rte_classify.py +160 -191
- {nltk-3.2 → nltk-3.3}/nltk/classify/scikitlearn.py +153 -151
- {nltk-3.2 → nltk-3.3}/nltk/classify/senna.py +183 -181
- {nltk-3.2 → nltk-3.3}/nltk/classify/svm.py +15 -15
- {nltk-3.2 → nltk-3.3}/nltk/classify/tadm.py +113 -112
- {nltk-3.2 → nltk-3.3}/nltk/classify/textcat.py +193 -193
- {nltk-3.2 → nltk-3.3}/nltk/classify/util.py +324 -312
- {nltk-3.2 → nltk-3.3}/nltk/classify/weka.py +346 -345
- {nltk-3.2 → nltk-3.3}/nltk/cluster/__init__.py +86 -86
- {nltk-3.2 → nltk-3.3}/nltk/cluster/api.py +74 -70
- {nltk-3.2 → nltk-3.3}/nltk/cluster/em.py +247 -247
- {nltk-3.2 → nltk-3.3}/nltk/cluster/gaac.py +168 -168
- {nltk-3.2 → nltk-3.3}/nltk/cluster/kmeans.py +221 -221
- {nltk-3.2 → nltk-3.3}/nltk/cluster/util.py +304 -289
- nltk-3.3/nltk/collections.py +640 -0
- {nltk-3.2 → nltk-3.3}/nltk/collocations.py +388 -388
- nltk-3.3/nltk/compat.py +365 -0
- {nltk-3.2 → nltk-3.3}/nltk/corpus/__init__.py +341 -320
- {nltk-3.2 → nltk-3.3}/nltk/corpus/europarl_raw.py +44 -44
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/__init__.py +147 -145
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/aligned.py +115 -114
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/api.py +448 -446
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/bnc.py +252 -252
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/bracket_parse.py +227 -227
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/categorized_sents.py +179 -178
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/chasen.py +140 -139
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/childes.py +522 -494
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/chunked.py +212 -212
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/cmudict.py +97 -95
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/comparative_sents.py +280 -278
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/conll.py +528 -521
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/crubadan.py +116 -116
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/dependency.py +101 -101
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/framenet.py +3059 -2093
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/ieer.py +112 -111
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/indian.py +85 -86
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/ipipan.py +332 -331
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/knbc.py +187 -187
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/lin.py +156 -156
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/mte.py +311 -310
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/nkjp.py +429 -428
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/nombank.py +421 -421
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/nps_chat.py +73 -73
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/opinion_lexicon.py +115 -115
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/panlex_lite.py +165 -165
- nltk-3.3/nltk/corpus/reader/pl196x.py +292 -0
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/plaintext.py +232 -233
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/ppattach.py +96 -95
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/propbank.py +479 -481
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/pros_cons.py +128 -126
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/reviews.py +330 -328
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/rte.py +144 -146
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/semcor.py +256 -256
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/senseval.py +203 -201
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/sentiwordnet.py +137 -137
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/sinica_treebank.py +75 -75
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/string_category.py +60 -59
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/switchboard.py +119 -119
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/tagged.py +295 -294
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/timit.py +452 -450
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/toolbox.py +68 -68
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/twitter.py +155 -157
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/udhr.py +80 -80
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/util.py +804 -800
- nltk-3.3/nltk/corpus/reader/verbnet.py +595 -0
- nltk-3.3/nltk/corpus/reader/wordlist.py +134 -0
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/wordnet.py +2108 -2036
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/xmldocs.py +392 -387
- {nltk-3.2 → nltk-3.3}/nltk/corpus/reader/ycoe.py +243 -242
- {nltk-3.2 → nltk-3.3}/nltk/corpus/util.py +144 -127
- {nltk-3.2 → nltk-3.3}/nltk/data.py +1487 -1451
- {nltk-3.2 → nltk-3.3}/nltk/decorators.py +219 -215
- {nltk-3.2 → nltk-3.3}/nltk/downloader.py +2278 -2274
- {nltk-3.2 → nltk-3.3}/nltk/draw/__init__.py +27 -27
- {nltk-3.2 → nltk-3.3}/nltk/draw/cfg.py +774 -777
- {nltk-3.2 → nltk-3.3}/nltk/draw/dispersion.py +58 -58
- {nltk-3.2 → nltk-3.3}/nltk/draw/table.py +1098 -1098
- {nltk-3.2 → nltk-3.3}/nltk/draw/tree.py +963 -966
- {nltk-3.2 → nltk-3.3}/nltk/draw/util.py +2356 -2356
- {nltk-3.2 → nltk-3.3}/nltk/featstruct.py +2617 -2500
- {nltk-3.2 → nltk-3.3}/nltk/grammar.py +1559 -1516
- {nltk-3.2 → nltk-3.3}/nltk/help.py +56 -56
- {nltk-3.2 → nltk-3.3}/nltk/inference/__init__.py +20 -20
- {nltk-3.2 → nltk-3.3}/nltk/inference/api.py +597 -589
- {nltk-3.2 → nltk-3.3}/nltk/inference/discourse.py +612 -608
- {nltk-3.2 → nltk-3.3}/nltk/inference/mace.py +311 -311
- {nltk-3.2 → nltk-3.3}/nltk/inference/nonmonotonic.py +509 -509
- {nltk-3.2 → nltk-3.3}/nltk/inference/prover9.py +431 -431
- {nltk-3.2 → nltk-3.3}/nltk/inference/resolution.py +687 -687
- {nltk-3.2 → nltk-3.3}/nltk/inference/tableau.py +607 -607
- {nltk-3.2 → nltk-3.3}/nltk/internals.py +982 -982
- {nltk-3.2 → nltk-3.3}/nltk/jsontags.py +63 -63
- {nltk-3.2 → nltk-3.3}/nltk/lazyimport.py +142 -142
- {nltk-3.2 → nltk-3.3}/nltk/metrics/__init__.py +30 -29
- {nltk-3.2 → nltk-3.3}/nltk/metrics/agreement.py +421 -401
- nltk-3.3/nltk/metrics/aline.py +607 -0
- {nltk-3.2 → nltk-3.3}/nltk/metrics/association.py +414 -410
- {nltk-3.2 → nltk-3.3}/nltk/metrics/confusionmatrix.py +206 -206
- {nltk-3.2 → nltk-3.3}/nltk/metrics/distance.py +207 -202
- {nltk-3.2 → nltk-3.3}/nltk/metrics/paice.py +381 -381
- {nltk-3.2 → nltk-3.3}/nltk/metrics/scores.py +228 -228
- {nltk-3.2 → nltk-3.3}/nltk/metrics/segmentation.py +231 -232
- {nltk-3.2 → nltk-3.3}/nltk/metrics/spearman.py +69 -69
- {nltk-3.2 → nltk-3.3}/nltk/misc/__init__.py +11 -11
- {nltk-3.2 → nltk-3.3}/nltk/misc/babelfish.py +10 -10
- {nltk-3.2 → nltk-3.3}/nltk/misc/chomsky.py +135 -133
- {nltk-3.2 → nltk-3.3}/nltk/misc/minimalset.py +83 -83
- {nltk-3.2 → nltk-3.3}/nltk/misc/sort.py +157 -157
- {nltk-3.2 → nltk-3.3}/nltk/misc/wordfinder.py +129 -129
- {nltk-3.2 → nltk-3.3}/nltk/parse/__init__.py +81 -80
- {nltk-3.2 → nltk-3.3}/nltk/parse/api.py +66 -66
- {nltk-3.2 → nltk-3.3}/nltk/parse/bllip.py +282 -282
- {nltk-3.2 → nltk-3.3}/nltk/parse/chart.py +1682 -1681
- nltk-3.3/nltk/parse/corenlp.py +780 -0
- {nltk-3.2 → nltk-3.3}/nltk/parse/dependencygraph.py +760 -758
- {nltk-3.2 → nltk-3.3}/nltk/parse/earleychart.py +452 -451
- {nltk-3.2 → nltk-3.3}/nltk/parse/evaluate.py +129 -129
- {nltk-3.2 → nltk-3.3}/nltk/parse/featurechart.py +580 -578
- {nltk-3.2 → nltk-3.3}/nltk/parse/generate.py +87 -76
- {nltk-3.2 → nltk-3.3}/nltk/parse/malt.py +356 -356
- {nltk-3.2 → nltk-3.3}/nltk/parse/nonprojectivedependencyparser.py +783 -783
- {nltk-3.2 → nltk-3.3}/nltk/parse/pchart.py +522 -522
- {nltk-3.2 → nltk-3.3}/nltk/parse/projectivedependencyparser.py +579 -578
- {nltk-3.2 → nltk-3.3}/nltk/parse/recursivedescent.py +655 -656
- {nltk-3.2 → nltk-3.3}/nltk/parse/shiftreduce.py +458 -459
- {nltk-3.2 → nltk-3.3}/nltk/parse/stanford.py +431 -406
- {nltk-3.2 → nltk-3.3}/nltk/parse/transitionparser.py +774 -772
- {nltk-3.2 → nltk-3.3}/nltk/parse/util.py +231 -231
- {nltk-3.2 → nltk-3.3}/nltk/parse/viterbi.py +401 -401
- {nltk-3.2 → nltk-3.3}/nltk/probability.py +2410 -2355
- {nltk-3.2 → nltk-3.3}/nltk/sem/__init__.py +61 -61
- {nltk-3.2 → nltk-3.3}/nltk/sem/boxer.py +1261 -1261
- {nltk-3.2 → nltk-3.3}/nltk/sem/chat80.py +782 -782
- {nltk-3.2 → nltk-3.3}/nltk/sem/cooper_storage.py +118 -118
- {nltk-3.2 → nltk-3.3}/nltk/sem/drt.py +1258 -1257
- {nltk-3.2 → nltk-3.3}/nltk/sem/drt_glue_demo.py +485 -489
- {nltk-3.2 → nltk-3.3}/nltk/sem/evaluate.py +790 -784
- {nltk-3.2 → nltk-3.3}/nltk/sem/glue.py +696 -694
- {nltk-3.2 → nltk-3.3}/nltk/sem/hole.py +386 -384
- {nltk-3.2 → nltk-3.3}/nltk/sem/lfg.py +210 -208
- {nltk-3.2 → nltk-3.3}/nltk/sem/linearlogic.py +451 -449
- {nltk-3.2 → nltk-3.3}/nltk/sem/logic.py +1910 -1910
- {nltk-3.2 → nltk-3.3}/nltk/sem/relextract.py +476 -483
- {nltk-3.2 → nltk-3.3}/nltk/sem/skolemize.py +101 -101
- {nltk-3.2 → nltk-3.3}/nltk/sem/util.py +249 -249
- {nltk-3.2 → nltk-3.3}/nltk/sentiment/__init__.py +14 -14
- {nltk-3.2 → nltk-3.3}/nltk/sentiment/sentiment_analyzer.py +229 -229
- {nltk-3.2 → nltk-3.3}/nltk/sentiment/util.py +762 -752
- {nltk-3.2 → nltk-3.3}/nltk/sentiment/vader.py +443 -445
- {nltk-3.2 → nltk-3.3}/nltk/stem/__init__.py +31 -33
- {nltk-3.2 → nltk-3.3}/nltk/stem/api.py +28 -25
- nltk-3.3/nltk/stem/arlstem.py +369 -0
- {nltk-3.2 → nltk-3.3}/nltk/stem/isri.py +345 -345
- {nltk-3.2 → nltk-3.3}/nltk/stem/lancaster.py +337 -310
- nltk-3.3/nltk/stem/porter.py +710 -0
- {nltk-3.2 → nltk-3.3}/nltk/stem/regexp.py +61 -61
- {nltk-3.2 → nltk-3.3}/nltk/stem/rslp.py +142 -142
- {nltk-3.2 → nltk-3.3}/nltk/stem/snowball.py +4236 -3712
- {nltk-3.2 → nltk-3.3}/nltk/stem/util.py +22 -12
- {nltk-3.2 → nltk-3.3}/nltk/stem/wordnet.py +51 -51
- {nltk-3.2 → nltk-3.3}/nltk/tag/__init__.py +152 -127
- {nltk-3.2 → nltk-3.3}/nltk/tag/api.py +86 -81
- {nltk-3.2 → nltk-3.3}/nltk/tag/brill.py +424 -426
- {nltk-3.2 → nltk-3.3}/nltk/tag/brill_trainer.py +608 -608
- {nltk-3.2 → nltk-3.3}/nltk/tag/crf.py +204 -200
- {nltk-3.2 → nltk-3.3}/nltk/tag/hmm.py +1277 -1277
- {nltk-3.2 → nltk-3.3}/nltk/tag/hunpos.py +132 -132
- {nltk-3.2 → nltk-3.3}/nltk/tag/mapping.py +101 -101
- {nltk-3.2 → nltk-3.3}/nltk/tag/perceptron.py +329 -314
- {nltk-3.2 → nltk-3.3}/nltk/tag/senna.py +147 -145
- {nltk-3.2 → nltk-3.3}/nltk/tag/sequential.py +740 -736
- {nltk-3.2 → nltk-3.3}/nltk/tag/stanford.py +219 -196
- {nltk-3.2 → nltk-3.3}/nltk/tag/tnt.py +595 -604
- {nltk-3.2 → nltk-3.3}/nltk/tag/util.py +72 -72
- {nltk-3.2 → nltk-3.3}/nltk/tbl/__init__.py +28 -28
- {nltk-3.2 → nltk-3.3}/nltk/tbl/api.py +1 -1
- {nltk-3.2 → nltk-3.3}/nltk/tbl/demo.py +366 -366
- {nltk-3.2 → nltk-3.3}/nltk/tbl/erroranalysis.py +39 -39
- {nltk-3.2 → nltk-3.3}/nltk/tbl/feature.py +259 -261
- {nltk-3.2 → nltk-3.3}/nltk/tbl/rule.py +321 -321
- {nltk-3.2 → nltk-3.3}/nltk/tbl/template.py +303 -308
- {nltk-3.2 → nltk-3.3}/nltk/test/__init__.py +18 -18
- {nltk-3.2 → nltk-3.3}/nltk/test/all.py +24 -23
- {nltk-3.2 → nltk-3.3}/nltk/test/bleu.doctest +14 -14
- {nltk-3.2 → nltk-3.3}/nltk/test/bnc.doctest +60 -60
- {nltk-3.2 → nltk-3.3}/nltk/test/ccg.doctest +376 -395
- nltk-3.3/nltk/test/ccg_semantics.doctest +553 -0
- {nltk-3.2 → nltk-3.3}/nltk/test/chat80.doctest +234 -234
- {nltk-3.2 → nltk-3.3}/nltk/test/childes.doctest +184 -184
- {nltk-3.2 → nltk-3.3}/nltk/test/childes_fixt.py +14 -13
- {nltk-3.2 → nltk-3.3}/nltk/test/chunk.doctest +373 -373
- {nltk-3.2 → nltk-3.3}/nltk/test/classify.doctest +185 -185
- {nltk-3.2 → nltk-3.3}/nltk/test/classify_fixt.py +11 -10
- nltk-3.3/nltk/test/collections.doctest +20 -0
- {nltk-3.2 → nltk-3.3}/nltk/test/collocations.doctest +276 -276
- {nltk-3.2 → nltk-3.3}/nltk/test/compat.doctest +134 -138
- {nltk-3.2 → nltk-3.3}/nltk/test/compat_fixt.py +9 -8
- nltk-3.3/nltk/test/concordance.doctest +55 -0
- {nltk-3.2 → nltk-3.3}/nltk/test/corpus.doctest +2200 -2212
- {nltk-3.2 → nltk-3.3}/nltk/test/corpus_fixt.py +3 -3
- {nltk-3.2 → nltk-3.3}/nltk/test/crubadan.doctest +65 -65
- {nltk-3.2 → nltk-3.3}/nltk/test/data.doctest +379 -379
- {nltk-3.2 → nltk-3.3}/nltk/test/dependency.doctest +241 -241
- {nltk-3.2 → nltk-3.3}/nltk/test/discourse.doctest +546 -546
- {nltk-3.2 → nltk-3.3}/nltk/test/discourse_fixt.py +14 -13
- {nltk-3.2 → nltk-3.3}/nltk/test/doctest_nose_plugin.py +159 -156
- {nltk-3.2 → nltk-3.3}/nltk/test/drt.doctest +517 -517
- {nltk-3.2 → nltk-3.3}/nltk/test/featgram.doctest +607 -607
- {nltk-3.2 → nltk-3.3}/nltk/test/featstruct.doctest +1229 -1230
- {nltk-3.2 → nltk-3.3}/nltk/test/framenet.doctest +288 -239
- {nltk-3.2 → nltk-3.3}/nltk/test/generate.doctest +67 -67
- {nltk-3.2 → nltk-3.3}/nltk/test/gensim.doctest +140 -141
- {nltk-3.2 → nltk-3.3}/nltk/test/gensim_fixt.py +10 -9
- {nltk-3.2 → nltk-3.3}/nltk/test/gluesemantics.doctest +384 -386
- {nltk-3.2 → nltk-3.3}/nltk/test/gluesemantics_malt.doctest +68 -68
- {nltk-3.2 → nltk-3.3}/nltk/test/gluesemantics_malt_fixt.py +12 -11
- {nltk-3.2 → nltk-3.3}/nltk/test/grammar.doctest +48 -48
- {nltk-3.2 → nltk-3.3}/nltk/test/grammartestsuites.doctest +109 -109
- {nltk-3.2 → nltk-3.3}/nltk/test/index.doctest +100 -100
- {nltk-3.2 → nltk-3.3}/nltk/test/inference.doctest +534 -534
- {nltk-3.2 → nltk-3.3}/nltk/test/inference_fixt.py +12 -11
- {nltk-3.2 → nltk-3.3}/nltk/test/internals.doctest +140 -140
- {nltk-3.2 → nltk-3.3}/nltk/test/japanese.doctest +48 -48
- {nltk-3.2 → nltk-3.3}/nltk/test/logic.doctest +1098 -1098
- {nltk-3.2 → nltk-3.3}/nltk/test/metrics.doctest +270 -270
- {nltk-3.2 → nltk-3.3}/nltk/test/misc.doctest +118 -118
- {nltk-3.2 → nltk-3.3}/nltk/test/nonmonotonic.doctest +286 -286
- {nltk-3.2 → nltk-3.3}/nltk/test/nonmonotonic_fixt.py +12 -11
- {nltk-3.2 → nltk-3.3}/nltk/test/paice.doctest +35 -35
- {nltk-3.2 → nltk-3.3}/nltk/test/parse.doctest +884 -884
- {nltk-3.2 → nltk-3.3}/nltk/test/portuguese_en.doctest +565 -565
- {nltk-3.2 → nltk-3.3}/nltk/test/portuguese_en_fixt.py +16 -16
- {nltk-3.2 → nltk-3.3}/nltk/test/probability.doctest +304 -304
- {nltk-3.2 → nltk-3.3}/nltk/test/probability_fixt.py +13 -12
- {nltk-3.2 → nltk-3.3}/nltk/test/propbank.doctest +176 -176
- {nltk-3.2 → nltk-3.3}/nltk/test/relextract.doctest +263 -263
- {nltk-3.2 → nltk-3.3}/nltk/test/resolution.doctest +221 -221
- {nltk-3.2 → nltk-3.3}/nltk/test/runtests.py +86 -64
- {nltk-3.2 → nltk-3.3}/nltk/test/segmentation_fixt.py +10 -10
- {nltk-3.2 → nltk-3.3}/nltk/test/semantics.doctest +665 -665
- {nltk-3.2 → nltk-3.3}/nltk/test/semantics_fixt.py +7 -7
- {nltk-3.2 → nltk-3.3}/nltk/test/sentiment.doctest +233 -233
- {nltk-3.2 → nltk-3.3}/nltk/test/sentiwordnet.doctest +41 -41
- {nltk-3.2 → nltk-3.3}/nltk/test/simple.doctest +85 -85
- {nltk-3.2 → nltk-3.3}/nltk/test/stem.doctest +78 -78
- {nltk-3.2 → nltk-3.3}/nltk/test/tag.doctest +33 -33
- {nltk-3.2 → nltk-3.3}/nltk/test/tokenize.doctest +273 -166
- {nltk-3.2 → nltk-3.3}/nltk/test/toolbox.doctest +307 -307
- {nltk-3.2 → nltk-3.3}/nltk/test/translate.doctest +242 -242
- {nltk-3.2 → nltk-3.3}/nltk/test/translate_fixt.py +3 -3
- {nltk-3.2 → nltk-3.3}/nltk/test/tree.doctest +1101 -1101
- {nltk-3.2 → nltk-3.3}/nltk/test/treeprettyprinter.doctest +127 -127
- {nltk-3.2 → nltk-3.3}/nltk/test/treetransforms.doctest +156 -156
- nltk-3.3/nltk/test/unit/test_2x_compat.py +63 -0
- nltk-3.3/nltk/test/unit/test_aline.py +52 -0
- nltk-3.3/nltk/test/unit/test_chunk.py +56 -0
- {nltk-3.2 → nltk-3.3}/nltk/test/unit/test_classify.py +55 -53
- {nltk-3.2 → nltk-3.3}/nltk/test/unit/test_collocations.py +88 -79
- nltk-3.3/nltk/test/unit/test_concordance.py +98 -0
- nltk-3.3/nltk/test/unit/test_corenlp.py +1000 -0
- {nltk-3.2 → nltk-3.3}/nltk/test/unit/test_corpora.py +200 -183
- {nltk-3.2 → nltk-3.3}/nltk/test/unit/test_corpus_views.py +45 -45
- {nltk-3.2 → nltk-3.3}/nltk/test/unit/test_hmm.py +88 -88
- {nltk-3.2 → nltk-3.3}/nltk/test/unit/test_json2csv_corpus.py +188 -187
- {nltk-3.2 → nltk-3.3}/nltk/test/unit/test_naivebayes.py +26 -26
- nltk-3.3/nltk/test/unit/test_rte_classify.py +86 -0
- {nltk-3.2 → nltk-3.3}/nltk/test/unit/test_seekable_unicode_stream_reader.py +124 -124
- nltk-3.3/nltk/test/unit/test_senna.py +74 -0
- nltk-3.3/nltk/test/unit/test_stem.py +121 -0
- {nltk-3.2 → nltk-3.3}/nltk/test/unit/test_tag.py +20 -20
- {nltk-3.2 → nltk-3.3}/nltk/test/unit/test_tgrep.py +628 -626
- nltk-3.3/nltk/test/unit/test_tokenize.py +168 -0
- {nltk-3.2 → nltk-3.3}/nltk/test/unit/test_twitter_auth.py +185 -185
- nltk-3.3/nltk/test/unit/test_wordnet.py +134 -0
- nltk-3.3/nltk/test/unit/translate/test_bleu.py +244 -0
- nltk-3.3/nltk/test/unit/translate/test_gdfa.py +57 -0
- {nltk-3.2 → nltk-3.3}/nltk/test/unit/translate/test_ibm1.py +75 -75
- {nltk-3.2 → nltk-3.3}/nltk/test/unit/translate/test_ibm2.py +87 -87
- {nltk-3.2 → nltk-3.3}/nltk/test/unit/translate/test_ibm3.py +105 -105
- {nltk-3.2 → nltk-3.3}/nltk/test/unit/translate/test_ibm4.py +126 -126
- {nltk-3.2 → nltk-3.3}/nltk/test/unit/translate/test_ibm5.py +166 -166
- {nltk-3.2 → nltk-3.3}/nltk/test/unit/translate/test_ibm_model.py +270 -270
- nltk-3.3/nltk/test/unit/translate/test_nist.py +37 -0
- {nltk-3.2 → nltk-3.3}/nltk/test/unit/translate/test_stack_decoder.py +300 -300
- {nltk-3.2 → nltk-3.3}/nltk/test/unit/utils.py +41 -41
- {nltk-3.2 → nltk-3.3}/nltk/test/util.doctest +48 -48
- {nltk-3.2 → nltk-3.3}/nltk/test/wordnet.doctest +595 -581
- {nltk-3.2 → nltk-3.3}/nltk/test/wordnet_fixt.py +7 -6
- {nltk-3.2 → nltk-3.3}/nltk/test/wordnet_lch.doctest +53 -53
- {nltk-3.2 → nltk-3.3}/nltk/test/wsd.doctest +68 -68
- {nltk-3.2 → nltk-3.3}/nltk/text.py +663 -610
- {nltk-3.2 → nltk-3.3}/nltk/tgrep.py +938 -937
- {nltk-3.2 → nltk-3.3}/nltk/tokenize/__init__.py +130 -107
- {nltk-3.2 → nltk-3.3}/nltk/tokenize/api.py +77 -78
- {nltk-3.2 → nltk-3.3}/nltk/tokenize/casual.py +343 -342
- {nltk-3.2 → nltk-3.3}/nltk/tokenize/mwe.py +120 -120
- nltk-3.3/nltk/tokenize/nist.py +173 -0
- {nltk-3.2 → nltk-3.3}/nltk/tokenize/punkt.py +1620 -1601
- {nltk-3.2 → nltk-3.3}/nltk/tokenize/regexp.py +208 -202
- nltk-3.3/nltk/tokenize/repp.py +151 -0
- {nltk-3.2 → nltk-3.3}/nltk/tokenize/sexpr.py +140 -142
- {nltk-3.2 → nltk-3.3}/nltk/tokenize/simple.py +138 -136
- {nltk-3.2 → nltk-3.3}/nltk/tokenize/stanford.py +117 -113
- nltk-3.3/nltk/tokenize/stanford_segmenter.py +246 -0
- {nltk-3.2 → nltk-3.3}/nltk/tokenize/texttiling.py +458 -460
- nltk-3.3/nltk/tokenize/toktok.py +155 -0
- nltk-3.3/nltk/tokenize/treebank.py +363 -0
- nltk-3.3/nltk/tokenize/util.py +261 -0
- {nltk-3.2 → nltk-3.3}/nltk/toolbox.py +499 -497
- {nltk-3.2 → nltk-3.3}/nltk/translate/__init__.py +24 -24
- {nltk-3.2 → nltk-3.3}/nltk/translate/api.py +331 -321
- {nltk-3.2 → nltk-3.3}/nltk/translate/bleu_score.py +615 -556
- nltk-3.3/nltk/translate/chrf_score.py +137 -0
- {nltk-3.2 → nltk-3.3}/nltk/translate/gale_church.py +248 -235
- {nltk-3.2 → nltk-3.3}/nltk/translate/gdfa.py +135 -131
- nltk-3.3/nltk/translate/gleu_score.py +193 -0
- {nltk-3.2 → nltk-3.3}/nltk/translate/ibm1.py +250 -241
- {nltk-3.2 → nltk-3.3}/nltk/translate/ibm2.py +308 -308
- {nltk-3.2 → nltk-3.3}/nltk/translate/ibm3.py +337 -337
- {nltk-3.2 → nltk-3.3}/nltk/translate/ibm4.py +467 -467
- {nltk-3.2 → nltk-3.3}/nltk/translate/ibm5.py +639 -639
- {nltk-3.2 → nltk-3.3}/nltk/translate/ibm_model.py +536 -533
- {nltk-3.2 → nltk-3.3}/nltk/translate/metrics.py +40 -40
- nltk-3.3/nltk/translate/nist_score.py +178 -0
- {nltk-3.2 → nltk-3.3}/nltk/translate/phrase_based.py +175 -175
- {nltk-3.2 → nltk-3.3}/nltk/translate/ribes_score.py +325 -325
- {nltk-3.2 → nltk-3.3}/nltk/translate/stack_decoder.py +499 -495
- {nltk-3.2 → nltk-3.3}/nltk/tree.py +1605 -1603
- {nltk-3.2 → nltk-3.3}/nltk/treeprettyprinter.py +564 -564
- {nltk-3.2 → nltk-3.3}/nltk/treetransforms.py +309 -309
- {nltk-3.2 → nltk-3.3}/nltk/twitter/__init__.py +28 -28
- {nltk-3.2 → nltk-3.3}/nltk/twitter/api.py +141 -136
- {nltk-3.2 → nltk-3.3}/nltk/twitter/common.py +264 -258
- {nltk-3.2 → nltk-3.3}/nltk/twitter/twitter_demo.py +288 -288
- {nltk-3.2 → nltk-3.3}/nltk/twitter/twitterclient.py +530 -530
- {nltk-3.2 → nltk-3.3}/nltk/twitter/util.py +147 -146
- nltk-3.3/nltk/util.py +751 -0
- {nltk-3.2 → nltk-3.3}/nltk/wsd.py +53 -53
- {nltk-3.2 → nltk-3.3/nltk.egg-info}/PKG-INFO +13 -5
- {nltk-3.2 → nltk-3.3}/nltk.egg-info/SOURCES.txt +26 -3
- nltk-3.3/nltk.egg-info/requires.txt +31 -0
- {nltk-3.2 → nltk-3.3}/setup.cfg +0 -1
- {nltk-3.2 → nltk-3.3}/setup.py +102 -75
- nltk-3.2/nltk/VERSION +0 -1
- nltk-3.2/nltk/compat.py +0 -680
- nltk-3.2/nltk/corpus/reader/pl196x.py +0 -278
- nltk-3.2/nltk/corpus/reader/verbnet.py +0 -408
- nltk-3.2/nltk/corpus/reader/wordlist.py +0 -37
- nltk-3.2/nltk/sentiment/vader_lexicon.txt +0 -7517
- nltk-3.2/nltk/six.py +0 -868
- nltk-3.2/nltk/stem/porter.py +0 -692
- nltk-3.2/nltk/test/unit/test_2x_compat.py +0 -26
- nltk-3.2/nltk/test/unit/test_stem.py +0 -36
- nltk-3.2/nltk/test/unit/test_tokenize.py +0 -23
- nltk-3.2/nltk/test/unit/translate/test_bleu.py +0 -84
- nltk-3.2/nltk/tokenize/treebank.py +0 -124
- nltk-3.2/nltk/tokenize/util.py +0 -90
- nltk-3.2/nltk/util.py +0 -1364
- {nltk-3.2 → nltk-3.3}/nltk/test/unit/__init__.py +0 -0
- {nltk-3.2 → nltk-3.3}/nltk/test/unit/translate/__init__.py +0 -0
- {nltk-3.2 → nltk-3.3}/nltk.egg-info/dependency_links.txt +0 -0
- {nltk-3.2 → nltk-3.3}/nltk.egg-info/not-zip-safe +0 -0
- {nltk-3.2 → nltk-3.3}/nltk.egg-info/top_level.txt +0 -0
|
@@ -1,966 +1,963 @@
|
|
|
1
|
-
# Natural Language Toolkit: Graphical Representations for Trees
|
|
2
|
-
#
|
|
3
|
-
# Copyright (C) 2001-
|
|
4
|
-
# Author: Edward Loper <edloper@gmail.com>
|
|
5
|
-
# URL: <http://nltk.org/>
|
|
6
|
-
# For license information, see LICENSE.TXT
|
|
7
|
-
|
|
8
|
-
"""
|
|
9
|
-
Graphically display a Tree.
|
|
10
|
-
"""
|
|
11
|
-
|
|
12
|
-
import
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
from
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
""
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
- ``
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
value is
|
|
50
|
-
- ``
|
|
51
|
-
|
|
52
|
-
value is
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
"""
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
self.
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
self.
|
|
69
|
-
self.
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
self.
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
for l in self._lines: canvas.itemconfig(l, state='
|
|
96
|
-
canvas.itemconfig(self._polygon, state='
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
elif attr == 'color':
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
canvas.itemconfig(
|
|
114
|
-
elif attr
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
return self.canvas().itemcget(
|
|
132
|
-
elif
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
elif attr == '
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
def
|
|
146
|
-
return self.
|
|
147
|
-
|
|
148
|
-
def
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
self.
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
self.
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
self.
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
self.
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
self.
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
if self._label
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
if
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
self.canvas().coords(self._polygon, nodex, nodey, xmin,
|
|
232
|
-
ymin,
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
(nodex, nodey
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
center
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
self.
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
``'
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
- ``
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
self.
|
|
495
|
-
|
|
496
|
-
#
|
|
497
|
-
self.
|
|
498
|
-
self.
|
|
499
|
-
self.
|
|
500
|
-
self.
|
|
501
|
-
self.
|
|
502
|
-
self.
|
|
503
|
-
self.
|
|
504
|
-
self.
|
|
505
|
-
self.
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
self.
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
self.
|
|
512
|
-
self.
|
|
513
|
-
self.
|
|
514
|
-
self.
|
|
515
|
-
self.
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
self.
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
#
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
for
|
|
642
|
-
elif attr == '
|
|
643
|
-
self.
|
|
644
|
-
for tseg in list(self._expanded_trees.values()): tseg['
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
for tseg in list(self._collapsed_trees.values()): tseg['
|
|
649
|
-
elif attr == '
|
|
650
|
-
self.
|
|
651
|
-
for tseg in list(self._collapsed_trees.values()): tseg['
|
|
652
|
-
elif attr == '
|
|
653
|
-
self.
|
|
654
|
-
for tseg in list(self.
|
|
655
|
-
|
|
656
|
-
self.
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
for
|
|
662
|
-
|
|
663
|
-
self.
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
self.
|
|
669
|
-
|
|
670
|
-
self.
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
self.
|
|
676
|
-
|
|
677
|
-
self.
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
self.
|
|
683
|
-
|
|
684
|
-
self.
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
elif attr
|
|
697
|
-
|
|
698
|
-
elif attr == '
|
|
699
|
-
elif attr == '
|
|
700
|
-
elif attr == '
|
|
701
|
-
elif attr == '
|
|
702
|
-
elif attr == '
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
new_treeseg.
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
#
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
self.
|
|
758
|
-
|
|
759
|
-
self._top
|
|
760
|
-
|
|
761
|
-
self.
|
|
762
|
-
self._top.bind('<Control-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
self.
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
filemenu.add_command(label='
|
|
808
|
-
command=self.
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
zoommenu
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
self.
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
widget['
|
|
836
|
-
widget['
|
|
837
|
-
widget['
|
|
838
|
-
widget['
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
self.
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
return
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
tc2.
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
treewidget.
|
|
928
|
-
treewidget
|
|
929
|
-
|
|
930
|
-
treewidget.
|
|
931
|
-
treewidget[
|
|
932
|
-
|
|
933
|
-
treewidget.
|
|
934
|
-
treewidget
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
from
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
cf.
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
tc4.
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
if __name__ == '__main__':
|
|
966
|
-
demo()
|
|
1
|
+
# Natural Language Toolkit: Graphical Representations for Trees
|
|
2
|
+
#
|
|
3
|
+
# Copyright (C) 2001-2018 NLTK Project
|
|
4
|
+
# Author: Edward Loper <edloper@gmail.com>
|
|
5
|
+
# URL: <http://nltk.org/>
|
|
6
|
+
# For license information, see LICENSE.TXT
|
|
7
|
+
|
|
8
|
+
"""
|
|
9
|
+
Graphically display a Tree.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from six.moves.tkinter import IntVar, Menu, Tk
|
|
13
|
+
|
|
14
|
+
from nltk.util import in_idle
|
|
15
|
+
from nltk.tree import Tree
|
|
16
|
+
from nltk.draw.util import (CanvasFrame, CanvasWidget, BoxWidget,
|
|
17
|
+
TextWidget, ParenWidget, OvalWidget)
|
|
18
|
+
|
|
19
|
+
##//////////////////////////////////////////////////////
|
|
20
|
+
## Tree Segment
|
|
21
|
+
##//////////////////////////////////////////////////////
|
|
22
|
+
|
|
23
|
+
class TreeSegmentWidget(CanvasWidget):
|
|
24
|
+
"""
|
|
25
|
+
A canvas widget that displays a single segment of a hierarchical
|
|
26
|
+
tree. Each ``TreeSegmentWidget`` connects a single "node widget"
|
|
27
|
+
to a sequence of zero or more "subtree widgets". By default, the
|
|
28
|
+
bottom of the node is connected to the top of each subtree by a
|
|
29
|
+
single line. However, if the ``roof`` attribute is set, then a
|
|
30
|
+
single triangular "roof" will connect the node to all of its
|
|
31
|
+
children.
|
|
32
|
+
|
|
33
|
+
Attributes:
|
|
34
|
+
- ``roof``: What sort of connection to draw between the node and
|
|
35
|
+
its subtrees. If ``roof`` is true, draw a single triangular
|
|
36
|
+
"roof" over the subtrees. If ``roof`` is false, draw a line
|
|
37
|
+
between each subtree and the node. Default value is false.
|
|
38
|
+
- ``xspace``: The amount of horizontal space to leave between
|
|
39
|
+
subtrees when managing this widget. Default value is 10.
|
|
40
|
+
- ``yspace``: The amount of space to place between the node and
|
|
41
|
+
its children when managing this widget. Default value is 15.
|
|
42
|
+
- ``color``: The color of the lines connecting the node to its
|
|
43
|
+
subtrees; and of the outline of the triangular roof. Default
|
|
44
|
+
value is ``'#006060'``.
|
|
45
|
+
- ``fill``: The fill color for the triangular roof. Default
|
|
46
|
+
value is ``''`` (no fill).
|
|
47
|
+
- ``width``: The width of the lines connecting the node to its
|
|
48
|
+
subtrees; and of the outline of the triangular roof. Default
|
|
49
|
+
value is 1.
|
|
50
|
+
- ``orientation``: Determines whether the tree branches downwards
|
|
51
|
+
or rightwards. Possible values are ``'horizontal'`` and
|
|
52
|
+
``'vertical'``. The default value is ``'vertical'`` (i.e.,
|
|
53
|
+
branch downwards).
|
|
54
|
+
- ``draggable``: whether the widget can be dragged by the user.
|
|
55
|
+
"""
|
|
56
|
+
def __init__(self, canvas, label, subtrees, **attribs):
|
|
57
|
+
"""
|
|
58
|
+
:type node:
|
|
59
|
+
:type subtrees: list(CanvasWidgetI)
|
|
60
|
+
"""
|
|
61
|
+
self._label = label
|
|
62
|
+
self._subtrees = subtrees
|
|
63
|
+
|
|
64
|
+
# Attributes
|
|
65
|
+
self._horizontal = 0
|
|
66
|
+
self._roof = 0
|
|
67
|
+
self._xspace = 10
|
|
68
|
+
self._yspace = 15
|
|
69
|
+
self._ordered = False
|
|
70
|
+
|
|
71
|
+
# Create canvas objects.
|
|
72
|
+
self._lines = [canvas.create_line(0,0,0,0, fill='#006060')
|
|
73
|
+
for c in subtrees]
|
|
74
|
+
self._polygon = canvas.create_polygon(0,0, fill='', state='hidden',
|
|
75
|
+
outline='#006060')
|
|
76
|
+
|
|
77
|
+
# Register child widgets (label + subtrees)
|
|
78
|
+
self._add_child_widget(label)
|
|
79
|
+
for subtree in subtrees:
|
|
80
|
+
self._add_child_widget(subtree)
|
|
81
|
+
|
|
82
|
+
# Are we currently managing?
|
|
83
|
+
self._managing = False
|
|
84
|
+
|
|
85
|
+
CanvasWidget.__init__(self, canvas, **attribs)
|
|
86
|
+
|
|
87
|
+
def __setitem__(self, attr, value):
|
|
88
|
+
canvas = self.canvas()
|
|
89
|
+
if attr == 'roof':
|
|
90
|
+
self._roof = value
|
|
91
|
+
if self._roof:
|
|
92
|
+
for l in self._lines: canvas.itemconfig(l, state='hidden')
|
|
93
|
+
canvas.itemconfig(self._polygon, state='normal')
|
|
94
|
+
else:
|
|
95
|
+
for l in self._lines: canvas.itemconfig(l, state='normal')
|
|
96
|
+
canvas.itemconfig(self._polygon, state='hidden')
|
|
97
|
+
elif attr == 'orientation':
|
|
98
|
+
if value == 'horizontal': self._horizontal = 1
|
|
99
|
+
elif value == 'vertical': self._horizontal = 0
|
|
100
|
+
else:
|
|
101
|
+
raise ValueError('orientation must be horizontal or vertical')
|
|
102
|
+
elif attr == 'color':
|
|
103
|
+
for l in self._lines: canvas.itemconfig(l, fill=value)
|
|
104
|
+
canvas.itemconfig(self._polygon, outline=value)
|
|
105
|
+
elif isinstance(attr, tuple) and attr[0] == 'color':
|
|
106
|
+
# Set the color of an individual line.
|
|
107
|
+
l = self._lines[int(attr[1])]
|
|
108
|
+
canvas.itemconfig(l, fill=value)
|
|
109
|
+
elif attr == 'fill':
|
|
110
|
+
canvas.itemconfig(self._polygon, fill=value)
|
|
111
|
+
elif attr == 'width':
|
|
112
|
+
canvas.itemconfig(self._polygon, {attr:value})
|
|
113
|
+
for l in self._lines: canvas.itemconfig(l, {attr:value})
|
|
114
|
+
elif attr in ('xspace', 'yspace'):
|
|
115
|
+
if attr == 'xspace': self._xspace = value
|
|
116
|
+
elif attr == 'yspace': self._yspace = value
|
|
117
|
+
self.update(self._label)
|
|
118
|
+
elif attr == 'ordered':
|
|
119
|
+
self._ordered = value
|
|
120
|
+
else:
|
|
121
|
+
CanvasWidget.__setitem__(self, attr, value)
|
|
122
|
+
|
|
123
|
+
def __getitem__(self, attr):
|
|
124
|
+
if attr == 'roof': return self._roof
|
|
125
|
+
elif attr == 'width':
|
|
126
|
+
return self.canvas().itemcget(self._polygon, attr)
|
|
127
|
+
elif attr == 'color':
|
|
128
|
+
return self.canvas().itemcget(self._polygon, 'outline')
|
|
129
|
+
elif isinstance(attr, tuple) and attr[0] == 'color':
|
|
130
|
+
l = self._lines[int(attr[1])]
|
|
131
|
+
return self.canvas().itemcget(l, 'fill')
|
|
132
|
+
elif attr == 'xspace': return self._xspace
|
|
133
|
+
elif attr == 'yspace': return self._yspace
|
|
134
|
+
elif attr == 'orientation':
|
|
135
|
+
if self._horizontal: return 'horizontal'
|
|
136
|
+
else: return 'vertical'
|
|
137
|
+
elif attr == 'ordered':
|
|
138
|
+
return self._ordered
|
|
139
|
+
else:
|
|
140
|
+
return CanvasWidget.__getitem__(self, attr)
|
|
141
|
+
|
|
142
|
+
def label(self):
|
|
143
|
+
return self._label
|
|
144
|
+
|
|
145
|
+
def subtrees(self):
|
|
146
|
+
return self._subtrees[:]
|
|
147
|
+
|
|
148
|
+
def set_label(self, label):
|
|
149
|
+
"""
|
|
150
|
+
Set the node label to ``label``.
|
|
151
|
+
"""
|
|
152
|
+
self._remove_child_widget(self._label)
|
|
153
|
+
self._add_child_widget(label)
|
|
154
|
+
self._label = label
|
|
155
|
+
self.update(self._label)
|
|
156
|
+
|
|
157
|
+
def replace_child(self, oldchild, newchild):
|
|
158
|
+
"""
|
|
159
|
+
Replace the child ``oldchild`` with ``newchild``.
|
|
160
|
+
"""
|
|
161
|
+
index = self._subtrees.index(oldchild)
|
|
162
|
+
self._subtrees[index] = newchild
|
|
163
|
+
self._remove_child_widget(oldchild)
|
|
164
|
+
self._add_child_widget(newchild)
|
|
165
|
+
self.update(newchild)
|
|
166
|
+
|
|
167
|
+
def remove_child(self, child):
|
|
168
|
+
index = self._subtrees.index(child)
|
|
169
|
+
del self._subtrees[index]
|
|
170
|
+
self._remove_child_widget(child)
|
|
171
|
+
self.canvas().delete(self._lines.pop())
|
|
172
|
+
self.update(self._label)
|
|
173
|
+
|
|
174
|
+
def insert_child(self, index, child):
|
|
175
|
+
canvas = self.canvas()
|
|
176
|
+
self._subtrees.insert(index, child)
|
|
177
|
+
self._add_child_widget(child)
|
|
178
|
+
self._lines.append(canvas.create_line(0,0,0,0, fill='#006060'))
|
|
179
|
+
self.update(self._label)
|
|
180
|
+
|
|
181
|
+
# but.. lines???
|
|
182
|
+
|
|
183
|
+
def _tags(self):
|
|
184
|
+
if self._roof:
|
|
185
|
+
return [self._polygon]
|
|
186
|
+
else:
|
|
187
|
+
return self._lines
|
|
188
|
+
|
|
189
|
+
def _subtree_top(self, child):
|
|
190
|
+
if isinstance(child, TreeSegmentWidget):
|
|
191
|
+
bbox = child.label().bbox()
|
|
192
|
+
else:
|
|
193
|
+
bbox = child.bbox()
|
|
194
|
+
if self._horizontal:
|
|
195
|
+
return (bbox[0], (bbox[1]+bbox[3])/2.0)
|
|
196
|
+
else:
|
|
197
|
+
return ((bbox[0]+bbox[2])/2.0, bbox[1])
|
|
198
|
+
|
|
199
|
+
def _node_bottom(self):
|
|
200
|
+
bbox = self._label.bbox()
|
|
201
|
+
if self._horizontal:
|
|
202
|
+
return (bbox[2], (bbox[1]+bbox[3])/2.0)
|
|
203
|
+
else:
|
|
204
|
+
return ((bbox[0]+bbox[2])/2.0, bbox[3])
|
|
205
|
+
|
|
206
|
+
def _update(self, child):
|
|
207
|
+
if len(self._subtrees) == 0: return
|
|
208
|
+
if self._label.bbox() is None: return # [XX] ???
|
|
209
|
+
|
|
210
|
+
# Which lines need to be redrawn?
|
|
211
|
+
if child is self._label: need_update = self._subtrees
|
|
212
|
+
else: need_update = [child]
|
|
213
|
+
|
|
214
|
+
if self._ordered and not self._managing:
|
|
215
|
+
need_update = self._maintain_order(child)
|
|
216
|
+
|
|
217
|
+
# Update the polygon.
|
|
218
|
+
(nodex, nodey) = self._node_bottom()
|
|
219
|
+
(xmin, ymin, xmax, ymax) = self._subtrees[0].bbox()
|
|
220
|
+
for subtree in self._subtrees[1:]:
|
|
221
|
+
bbox = subtree.bbox()
|
|
222
|
+
xmin = min(xmin, bbox[0])
|
|
223
|
+
ymin = min(ymin, bbox[1])
|
|
224
|
+
xmax = max(xmax, bbox[2])
|
|
225
|
+
ymax = max(ymax, bbox[3])
|
|
226
|
+
|
|
227
|
+
if self._horizontal:
|
|
228
|
+
self.canvas().coords(self._polygon, nodex, nodey, xmin,
|
|
229
|
+
ymin, xmin, ymax, nodex, nodey)
|
|
230
|
+
else:
|
|
231
|
+
self.canvas().coords(self._polygon, nodex, nodey, xmin,
|
|
232
|
+
ymin, xmax, ymin, nodex, nodey)
|
|
233
|
+
|
|
234
|
+
# Redraw all lines that need it.
|
|
235
|
+
for subtree in need_update:
|
|
236
|
+
(nodex, nodey) = self._node_bottom()
|
|
237
|
+
line = self._lines[self._subtrees.index(subtree)]
|
|
238
|
+
(subtreex, subtreey) = self._subtree_top(subtree)
|
|
239
|
+
self.canvas().coords(line, nodex, nodey, subtreex, subtreey)
|
|
240
|
+
|
|
241
|
+
def _maintain_order(self, child):
|
|
242
|
+
if self._horizontal:
|
|
243
|
+
return self._maintain_order_horizontal(child)
|
|
244
|
+
else:
|
|
245
|
+
return self._maintain_order_vertical(child)
|
|
246
|
+
|
|
247
|
+
def _maintain_order_vertical(self, child):
|
|
248
|
+
(left, top, right, bot) = child.bbox()
|
|
249
|
+
|
|
250
|
+
if child is self._label:
|
|
251
|
+
# Check all the leaves
|
|
252
|
+
for subtree in self._subtrees:
|
|
253
|
+
(x1, y1, x2, y2) = subtree.bbox()
|
|
254
|
+
if bot+self._yspace > y1:
|
|
255
|
+
subtree.move(0,bot+self._yspace-y1)
|
|
256
|
+
|
|
257
|
+
return self._subtrees
|
|
258
|
+
else:
|
|
259
|
+
moved = [child]
|
|
260
|
+
index = self._subtrees.index(child)
|
|
261
|
+
|
|
262
|
+
# Check leaves to our right.
|
|
263
|
+
x = right + self._xspace
|
|
264
|
+
for i in range(index+1, len(self._subtrees)):
|
|
265
|
+
(x1, y1, x2, y2) = self._subtrees[i].bbox()
|
|
266
|
+
if x > x1:
|
|
267
|
+
self._subtrees[i].move(x-x1, 0)
|
|
268
|
+
x += x2-x1 + self._xspace
|
|
269
|
+
moved.append(self._subtrees[i])
|
|
270
|
+
|
|
271
|
+
# Check leaves to our left.
|
|
272
|
+
x = left - self._xspace
|
|
273
|
+
for i in range(index-1, -1, -1):
|
|
274
|
+
(x1, y1, x2, y2) = self._subtrees[i].bbox()
|
|
275
|
+
if x < x2:
|
|
276
|
+
self._subtrees[i].move(x-x2, 0)
|
|
277
|
+
x -= x2-x1 + self._xspace
|
|
278
|
+
moved.append(self._subtrees[i])
|
|
279
|
+
|
|
280
|
+
# Check the node
|
|
281
|
+
(x1, y1, x2, y2) = self._label.bbox()
|
|
282
|
+
if y2 > top-self._yspace:
|
|
283
|
+
self._label.move(0, top-self._yspace-y2)
|
|
284
|
+
moved = self._subtrees
|
|
285
|
+
|
|
286
|
+
# Return a list of the nodes we moved
|
|
287
|
+
return moved
|
|
288
|
+
|
|
289
|
+
def _maintain_order_horizontal(self, child):
|
|
290
|
+
(left, top, right, bot) = child.bbox()
|
|
291
|
+
|
|
292
|
+
if child is self._label:
|
|
293
|
+
# Check all the leaves
|
|
294
|
+
for subtree in self._subtrees:
|
|
295
|
+
(x1, y1, x2, y2) = subtree.bbox()
|
|
296
|
+
if right+self._xspace > x1:
|
|
297
|
+
subtree.move(right+self._xspace-x1)
|
|
298
|
+
|
|
299
|
+
return self._subtrees
|
|
300
|
+
else:
|
|
301
|
+
moved = [child]
|
|
302
|
+
index = self._subtrees.index(child)
|
|
303
|
+
|
|
304
|
+
# Check leaves below us.
|
|
305
|
+
y = bot + self._yspace
|
|
306
|
+
for i in range(index+1, len(self._subtrees)):
|
|
307
|
+
(x1, y1, x2, y2) = self._subtrees[i].bbox()
|
|
308
|
+
if y > y1:
|
|
309
|
+
self._subtrees[i].move(0, y-y1)
|
|
310
|
+
y += y2-y1 + self._yspace
|
|
311
|
+
moved.append(self._subtrees[i])
|
|
312
|
+
|
|
313
|
+
# Check leaves above us
|
|
314
|
+
y = top - self._yspace
|
|
315
|
+
for i in range(index-1, -1, -1):
|
|
316
|
+
(x1, y1, x2, y2) = self._subtrees[i].bbox()
|
|
317
|
+
if y < y2:
|
|
318
|
+
self._subtrees[i].move(0, y-y2)
|
|
319
|
+
y -= y2-y1 + self._yspace
|
|
320
|
+
moved.append(self._subtrees[i])
|
|
321
|
+
|
|
322
|
+
# Check the node
|
|
323
|
+
(x1, y1, x2, y2) = self._label.bbox()
|
|
324
|
+
if x2 > left-self._xspace:
|
|
325
|
+
self._label.move(left-self._xspace-x2, 0)
|
|
326
|
+
moved = self._subtrees
|
|
327
|
+
|
|
328
|
+
# Return a list of the nodes we moved
|
|
329
|
+
return moved
|
|
330
|
+
|
|
331
|
+
def _manage_horizontal(self):
|
|
332
|
+
(nodex, nodey) = self._node_bottom()
|
|
333
|
+
|
|
334
|
+
# Put the subtrees in a line.
|
|
335
|
+
y = 20
|
|
336
|
+
for subtree in self._subtrees:
|
|
337
|
+
subtree_bbox = subtree.bbox()
|
|
338
|
+
dx = nodex - subtree_bbox[0] + self._xspace
|
|
339
|
+
dy = y - subtree_bbox[1]
|
|
340
|
+
subtree.move(dx, dy)
|
|
341
|
+
y += subtree_bbox[3] - subtree_bbox[1] + self._yspace
|
|
342
|
+
|
|
343
|
+
# Find the center of their tops.
|
|
344
|
+
center = 0.0
|
|
345
|
+
for subtree in self._subtrees:
|
|
346
|
+
center += self._subtree_top(subtree)[1]
|
|
347
|
+
center /= len(self._subtrees)
|
|
348
|
+
|
|
349
|
+
# Center the subtrees with the node.
|
|
350
|
+
for subtree in self._subtrees:
|
|
351
|
+
subtree.move(0, nodey-center)
|
|
352
|
+
|
|
353
|
+
def _manage_vertical(self):
|
|
354
|
+
(nodex, nodey) = self._node_bottom()
|
|
355
|
+
|
|
356
|
+
# Put the subtrees in a line.
|
|
357
|
+
x = 0
|
|
358
|
+
for subtree in self._subtrees:
|
|
359
|
+
subtree_bbox = subtree.bbox()
|
|
360
|
+
dy = nodey - subtree_bbox[1] + self._yspace
|
|
361
|
+
dx = x - subtree_bbox[0]
|
|
362
|
+
subtree.move(dx, dy)
|
|
363
|
+
x += subtree_bbox[2] - subtree_bbox[0] + self._xspace
|
|
364
|
+
|
|
365
|
+
# Find the center of their tops.
|
|
366
|
+
center = 0.0
|
|
367
|
+
for subtree in self._subtrees:
|
|
368
|
+
center += self._subtree_top(subtree)[0]/len(self._subtrees)
|
|
369
|
+
|
|
370
|
+
# Center the subtrees with the node.
|
|
371
|
+
for subtree in self._subtrees:
|
|
372
|
+
subtree.move(nodex-center, 0)
|
|
373
|
+
|
|
374
|
+
def _manage(self):
|
|
375
|
+
self._managing = True
|
|
376
|
+
(nodex, nodey) = self._node_bottom()
|
|
377
|
+
if len(self._subtrees) == 0: return
|
|
378
|
+
|
|
379
|
+
if self._horizontal: self._manage_horizontal()
|
|
380
|
+
else: self._manage_vertical()
|
|
381
|
+
|
|
382
|
+
# Update lines to subtrees.
|
|
383
|
+
for subtree in self._subtrees:
|
|
384
|
+
self._update(subtree)
|
|
385
|
+
|
|
386
|
+
self._managing = False
|
|
387
|
+
|
|
388
|
+
def __repr__(self):
|
|
389
|
+
return '[TreeSeg %s: %s]' % (self._label, self._subtrees)
|
|
390
|
+
|
|
391
|
+
def _tree_to_treeseg(canvas, t, make_node, make_leaf,
|
|
392
|
+
tree_attribs, node_attribs,
|
|
393
|
+
leaf_attribs, loc_attribs):
|
|
394
|
+
if isinstance(t, Tree):
|
|
395
|
+
label = make_node(canvas, t.label(), **node_attribs)
|
|
396
|
+
subtrees = [_tree_to_treeseg(canvas, child, make_node, make_leaf,
|
|
397
|
+
tree_attribs, node_attribs,
|
|
398
|
+
leaf_attribs, loc_attribs)
|
|
399
|
+
for child in t]
|
|
400
|
+
return TreeSegmentWidget(canvas, label, subtrees, **tree_attribs)
|
|
401
|
+
else:
|
|
402
|
+
return make_leaf(canvas, t, **leaf_attribs)
|
|
403
|
+
|
|
404
|
+
def tree_to_treesegment(canvas, t, make_node=TextWidget,
|
|
405
|
+
make_leaf=TextWidget, **attribs):
|
|
406
|
+
"""
|
|
407
|
+
Convert a Tree into a ``TreeSegmentWidget``.
|
|
408
|
+
|
|
409
|
+
:param make_node: A ``CanvasWidget`` constructor or a function that
|
|
410
|
+
creates ``CanvasWidgets``. ``make_node`` is used to convert
|
|
411
|
+
the Tree's nodes into ``CanvasWidgets``. If no constructor
|
|
412
|
+
is specified, then ``TextWidget`` will be used.
|
|
413
|
+
:param make_leaf: A ``CanvasWidget`` constructor or a function that
|
|
414
|
+
creates ``CanvasWidgets``. ``make_leaf`` is used to convert
|
|
415
|
+
the Tree's leafs into ``CanvasWidgets``. If no constructor
|
|
416
|
+
is specified, then ``TextWidget`` will be used.
|
|
417
|
+
:param attribs: Attributes for the canvas widgets that make up the
|
|
418
|
+
returned ``TreeSegmentWidget``. Any attribute beginning with
|
|
419
|
+
``'tree_'`` will be passed to all ``TreeSegmentWidgets`` (with
|
|
420
|
+
the ``'tree_'`` prefix removed. Any attribute beginning with
|
|
421
|
+
``'node_'`` will be passed to all nodes. Any attribute
|
|
422
|
+
beginning with ``'leaf_'`` will be passed to all leaves. And
|
|
423
|
+
any attribute beginning with ``'loc_'`` will be passed to all
|
|
424
|
+
text locations (for Trees).
|
|
425
|
+
"""
|
|
426
|
+
# Process attribs.
|
|
427
|
+
tree_attribs = {}
|
|
428
|
+
node_attribs = {}
|
|
429
|
+
leaf_attribs = {}
|
|
430
|
+
loc_attribs = {}
|
|
431
|
+
|
|
432
|
+
for (key, value) in list(attribs.items()):
|
|
433
|
+
if key[:5] == 'tree_': tree_attribs[key[5:]] = value
|
|
434
|
+
elif key[:5] == 'node_': node_attribs[key[5:]] = value
|
|
435
|
+
elif key[:5] == 'leaf_': leaf_attribs[key[5:]] = value
|
|
436
|
+
elif key[:4] == 'loc_': loc_attribs[key[4:]] = value
|
|
437
|
+
else: raise ValueError('Bad attribute: %s' % key)
|
|
438
|
+
return _tree_to_treeseg(canvas, t, make_node, make_leaf,
|
|
439
|
+
tree_attribs, node_attribs,
|
|
440
|
+
leaf_attribs, loc_attribs)
|
|
441
|
+
|
|
442
|
+
##//////////////////////////////////////////////////////
|
|
443
|
+
## Tree Widget
|
|
444
|
+
##//////////////////////////////////////////////////////
|
|
445
|
+
|
|
446
|
+
class TreeWidget(CanvasWidget):
|
|
447
|
+
"""
|
|
448
|
+
A canvas widget that displays a single Tree.
|
|
449
|
+
``TreeWidget`` manages a group of ``TreeSegmentWidgets`` that are
|
|
450
|
+
used to display a Tree.
|
|
451
|
+
|
|
452
|
+
Attributes:
|
|
453
|
+
|
|
454
|
+
- ``node_attr``: Sets the attribute ``attr`` on all of the
|
|
455
|
+
node widgets for this ``TreeWidget``.
|
|
456
|
+
- ``node_attr``: Sets the attribute ``attr`` on all of the
|
|
457
|
+
leaf widgets for this ``TreeWidget``.
|
|
458
|
+
- ``loc_attr``: Sets the attribute ``attr`` on all of the
|
|
459
|
+
location widgets for this ``TreeWidget`` (if it was built from
|
|
460
|
+
a Tree). Note that a location widget is a ``TextWidget``.
|
|
461
|
+
|
|
462
|
+
- ``xspace``: The amount of horizontal space to leave between
|
|
463
|
+
subtrees when managing this widget. Default value is 10.
|
|
464
|
+
- ``yspace``: The amount of space to place between the node and
|
|
465
|
+
its children when managing this widget. Default value is 15.
|
|
466
|
+
|
|
467
|
+
- ``line_color``: The color of the lines connecting each expanded
|
|
468
|
+
node to its subtrees.
|
|
469
|
+
- ``roof_color``: The color of the outline of the triangular roof
|
|
470
|
+
for collapsed trees.
|
|
471
|
+
- ``roof_fill``: The fill color for the triangular roof for
|
|
472
|
+
collapsed trees.
|
|
473
|
+
- ``width``
|
|
474
|
+
|
|
475
|
+
- ``orientation``: Determines whether the tree branches downwards
|
|
476
|
+
or rightwards. Possible values are ``'horizontal'`` and
|
|
477
|
+
``'vertical'``. The default value is ``'vertical'`` (i.e.,
|
|
478
|
+
branch downwards).
|
|
479
|
+
|
|
480
|
+
- ``shapeable``: whether the subtrees can be independently
|
|
481
|
+
dragged by the user. THIS property simply sets the
|
|
482
|
+
``DRAGGABLE`` property on all of the ``TreeWidget``'s tree
|
|
483
|
+
segments.
|
|
484
|
+
- ``draggable``: whether the widget can be dragged by the user.
|
|
485
|
+
"""
|
|
486
|
+
def __init__(self, canvas, t, make_node=TextWidget,
|
|
487
|
+
make_leaf=TextWidget, **attribs):
|
|
488
|
+
# Node & leaf canvas widget constructors
|
|
489
|
+
self._make_node = make_node
|
|
490
|
+
self._make_leaf = make_leaf
|
|
491
|
+
self._tree = t
|
|
492
|
+
|
|
493
|
+
# Attributes.
|
|
494
|
+
self._nodeattribs = {}
|
|
495
|
+
self._leafattribs = {}
|
|
496
|
+
self._locattribs = {'color': '#008000'}
|
|
497
|
+
self._line_color = '#008080'
|
|
498
|
+
self._line_width = 1
|
|
499
|
+
self._roof_color = '#008080'
|
|
500
|
+
self._roof_fill = '#c0c0c0'
|
|
501
|
+
self._shapeable = False
|
|
502
|
+
self._xspace = 10
|
|
503
|
+
self._yspace = 10
|
|
504
|
+
self._orientation = 'vertical'
|
|
505
|
+
self._ordered = False
|
|
506
|
+
|
|
507
|
+
# Build trees.
|
|
508
|
+
self._keys = {} # treeseg -> key
|
|
509
|
+
self._expanded_trees = {}
|
|
510
|
+
self._collapsed_trees = {}
|
|
511
|
+
self._nodes = []
|
|
512
|
+
self._leaves = []
|
|
513
|
+
#self._locs = []
|
|
514
|
+
self._make_collapsed_trees(canvas, t, ())
|
|
515
|
+
self._treeseg = self._make_expanded_tree(canvas, t, ())
|
|
516
|
+
self._add_child_widget(self._treeseg)
|
|
517
|
+
|
|
518
|
+
CanvasWidget.__init__(self, canvas, **attribs)
|
|
519
|
+
|
|
520
|
+
def expanded_tree(self, *path_to_tree):
|
|
521
|
+
"""
|
|
522
|
+
Return the ``TreeSegmentWidget`` for the specified subtree.
|
|
523
|
+
|
|
524
|
+
:param path_to_tree: A list of indices i1, i2, ..., in, where
|
|
525
|
+
the desired widget is the widget corresponding to
|
|
526
|
+
``tree.children()[i1].children()[i2]....children()[in]``.
|
|
527
|
+
For the root, the path is ``()``.
|
|
528
|
+
"""
|
|
529
|
+
return self._expanded_trees[path_to_tree]
|
|
530
|
+
|
|
531
|
+
def collapsed_tree(self, *path_to_tree):
|
|
532
|
+
"""
|
|
533
|
+
Return the ``TreeSegmentWidget`` for the specified subtree.
|
|
534
|
+
|
|
535
|
+
:param path_to_tree: A list of indices i1, i2, ..., in, where
|
|
536
|
+
the desired widget is the widget corresponding to
|
|
537
|
+
``tree.children()[i1].children()[i2]....children()[in]``.
|
|
538
|
+
For the root, the path is ``()``.
|
|
539
|
+
"""
|
|
540
|
+
return self._collapsed_trees[path_to_tree]
|
|
541
|
+
|
|
542
|
+
def bind_click_trees(self, callback, button=1):
|
|
543
|
+
"""
|
|
544
|
+
Add a binding to all tree segments.
|
|
545
|
+
"""
|
|
546
|
+
for tseg in list(self._expanded_trees.values()):
|
|
547
|
+
tseg.bind_click(callback, button)
|
|
548
|
+
for tseg in list(self._collapsed_trees.values()):
|
|
549
|
+
tseg.bind_click(callback, button)
|
|
550
|
+
|
|
551
|
+
def bind_drag_trees(self, callback, button=1):
|
|
552
|
+
"""
|
|
553
|
+
Add a binding to all tree segments.
|
|
554
|
+
"""
|
|
555
|
+
for tseg in list(self._expanded_trees.values()):
|
|
556
|
+
tseg.bind_drag(callback, button)
|
|
557
|
+
for tseg in list(self._collapsed_trees.values()):
|
|
558
|
+
tseg.bind_drag(callback, button)
|
|
559
|
+
|
|
560
|
+
def bind_click_leaves(self, callback, button=1):
|
|
561
|
+
"""
|
|
562
|
+
Add a binding to all leaves.
|
|
563
|
+
"""
|
|
564
|
+
for leaf in self._leaves: leaf.bind_click(callback, button)
|
|
565
|
+
for leaf in self._leaves: leaf.bind_click(callback, button)
|
|
566
|
+
|
|
567
|
+
def bind_drag_leaves(self, callback, button=1):
|
|
568
|
+
"""
|
|
569
|
+
Add a binding to all leaves.
|
|
570
|
+
"""
|
|
571
|
+
for leaf in self._leaves: leaf.bind_drag(callback, button)
|
|
572
|
+
for leaf in self._leaves: leaf.bind_drag(callback, button)
|
|
573
|
+
|
|
574
|
+
def bind_click_nodes(self, callback, button=1):
|
|
575
|
+
"""
|
|
576
|
+
Add a binding to all nodes.
|
|
577
|
+
"""
|
|
578
|
+
for node in self._nodes: node.bind_click(callback, button)
|
|
579
|
+
for node in self._nodes: node.bind_click(callback, button)
|
|
580
|
+
|
|
581
|
+
def bind_drag_nodes(self, callback, button=1):
|
|
582
|
+
"""
|
|
583
|
+
Add a binding to all nodes.
|
|
584
|
+
"""
|
|
585
|
+
for node in self._nodes: node.bind_drag(callback, button)
|
|
586
|
+
for node in self._nodes: node.bind_drag(callback, button)
|
|
587
|
+
|
|
588
|
+
def _make_collapsed_trees(self, canvas, t, key):
|
|
589
|
+
if not isinstance(t, Tree): return
|
|
590
|
+
make_node = self._make_node
|
|
591
|
+
make_leaf = self._make_leaf
|
|
592
|
+
|
|
593
|
+
node = make_node(canvas, t.label(), **self._nodeattribs)
|
|
594
|
+
self._nodes.append(node)
|
|
595
|
+
leaves = [make_leaf(canvas, l, **self._leafattribs)
|
|
596
|
+
for l in t.leaves()]
|
|
597
|
+
self._leaves += leaves
|
|
598
|
+
treeseg = TreeSegmentWidget(canvas, node, leaves, roof=1,
|
|
599
|
+
color=self._roof_color,
|
|
600
|
+
fill=self._roof_fill,
|
|
601
|
+
width=self._line_width)
|
|
602
|
+
|
|
603
|
+
self._collapsed_trees[key] = treeseg
|
|
604
|
+
self._keys[treeseg] = key
|
|
605
|
+
#self._add_child_widget(treeseg)
|
|
606
|
+
treeseg.hide()
|
|
607
|
+
|
|
608
|
+
# Build trees for children.
|
|
609
|
+
for i in range(len(t)):
|
|
610
|
+
child = t[i]
|
|
611
|
+
self._make_collapsed_trees(canvas, child, key + (i,))
|
|
612
|
+
|
|
613
|
+
def _make_expanded_tree(self, canvas, t, key):
|
|
614
|
+
make_node = self._make_node
|
|
615
|
+
make_leaf = self._make_leaf
|
|
616
|
+
|
|
617
|
+
if isinstance(t, Tree):
|
|
618
|
+
node = make_node(canvas, t.label(), **self._nodeattribs)
|
|
619
|
+
self._nodes.append(node)
|
|
620
|
+
children = t
|
|
621
|
+
subtrees = [self._make_expanded_tree(canvas, children[i], key+(i,))
|
|
622
|
+
for i in range(len(children))]
|
|
623
|
+
treeseg = TreeSegmentWidget(canvas, node, subtrees,
|
|
624
|
+
color=self._line_color,
|
|
625
|
+
width=self._line_width)
|
|
626
|
+
self._expanded_trees[key] = treeseg
|
|
627
|
+
self._keys[treeseg] = key
|
|
628
|
+
return treeseg
|
|
629
|
+
else:
|
|
630
|
+
leaf = make_leaf(canvas, t, **self._leafattribs)
|
|
631
|
+
self._leaves.append(leaf)
|
|
632
|
+
return leaf
|
|
633
|
+
|
|
634
|
+
def __setitem__(self, attr, value):
|
|
635
|
+
if attr[:5] == 'node_':
|
|
636
|
+
for node in self._nodes: node[attr[5:]] = value
|
|
637
|
+
elif attr[:5] == 'leaf_':
|
|
638
|
+
for leaf in self._leaves: leaf[attr[5:]] = value
|
|
639
|
+
elif attr == 'line_color':
|
|
640
|
+
self._line_color = value
|
|
641
|
+
for tseg in list(self._expanded_trees.values()): tseg['color'] = value
|
|
642
|
+
elif attr == 'line_width':
|
|
643
|
+
self._line_width = value
|
|
644
|
+
for tseg in list(self._expanded_trees.values()): tseg['width'] = value
|
|
645
|
+
for tseg in list(self._collapsed_trees.values()): tseg['width'] = value
|
|
646
|
+
elif attr == 'roof_color':
|
|
647
|
+
self._roof_color = value
|
|
648
|
+
for tseg in list(self._collapsed_trees.values()): tseg['color'] = value
|
|
649
|
+
elif attr == 'roof_fill':
|
|
650
|
+
self._roof_fill = value
|
|
651
|
+
for tseg in list(self._collapsed_trees.values()): tseg['fill'] = value
|
|
652
|
+
elif attr == 'shapeable':
|
|
653
|
+
self._shapeable = value
|
|
654
|
+
for tseg in list(self._expanded_trees.values()):
|
|
655
|
+
tseg['draggable'] = value
|
|
656
|
+
for tseg in list(self._collapsed_trees.values()):
|
|
657
|
+
tseg['draggable'] = value
|
|
658
|
+
for leaf in self._leaves: leaf['draggable'] = value
|
|
659
|
+
elif attr == 'xspace':
|
|
660
|
+
self._xspace = value
|
|
661
|
+
for tseg in list(self._expanded_trees.values()):
|
|
662
|
+
tseg['xspace'] = value
|
|
663
|
+
for tseg in list(self._collapsed_trees.values()):
|
|
664
|
+
tseg['xspace'] = value
|
|
665
|
+
self.manage()
|
|
666
|
+
elif attr == 'yspace':
|
|
667
|
+
self._yspace = value
|
|
668
|
+
for tseg in list(self._expanded_trees.values()):
|
|
669
|
+
tseg['yspace'] = value
|
|
670
|
+
for tseg in list(self._collapsed_trees.values()):
|
|
671
|
+
tseg['yspace'] = value
|
|
672
|
+
self.manage()
|
|
673
|
+
elif attr == 'orientation':
|
|
674
|
+
self._orientation = value
|
|
675
|
+
for tseg in list(self._expanded_trees.values()):
|
|
676
|
+
tseg['orientation'] = value
|
|
677
|
+
for tseg in list(self._collapsed_trees.values()):
|
|
678
|
+
tseg['orientation'] = value
|
|
679
|
+
self.manage()
|
|
680
|
+
elif attr == 'ordered':
|
|
681
|
+
self._ordered = value
|
|
682
|
+
for tseg in list(self._expanded_trees.values()):
|
|
683
|
+
tseg['ordered'] = value
|
|
684
|
+
for tseg in list(self._collapsed_trees.values()):
|
|
685
|
+
tseg['ordered'] = value
|
|
686
|
+
else: CanvasWidget.__setitem__(self, attr, value)
|
|
687
|
+
|
|
688
|
+
def __getitem__(self, attr):
|
|
689
|
+
if attr[:5] == 'node_':
|
|
690
|
+
return self._nodeattribs.get(attr[5:], None)
|
|
691
|
+
elif attr[:5] == 'leaf_':
|
|
692
|
+
return self._leafattribs.get(attr[5:], None)
|
|
693
|
+
elif attr[:4] == 'loc_':
|
|
694
|
+
return self._locattribs.get(attr[4:], None)
|
|
695
|
+
elif attr == 'line_color': return self._line_color
|
|
696
|
+
elif attr == 'line_width': return self._line_width
|
|
697
|
+
elif attr == 'roof_color': return self._roof_color
|
|
698
|
+
elif attr == 'roof_fill': return self._roof_fill
|
|
699
|
+
elif attr == 'shapeable': return self._shapeable
|
|
700
|
+
elif attr == 'xspace': return self._xspace
|
|
701
|
+
elif attr == 'yspace': return self._yspace
|
|
702
|
+
elif attr == 'orientation': return self._orientation
|
|
703
|
+
else: return CanvasWidget.__getitem__(self, attr)
|
|
704
|
+
|
|
705
|
+
def _tags(self): return []
|
|
706
|
+
|
|
707
|
+
def _manage(self):
|
|
708
|
+
segs = list(self._expanded_trees.values()) + list(self._collapsed_trees.values())
|
|
709
|
+
for tseg in segs:
|
|
710
|
+
if tseg.hidden():
|
|
711
|
+
tseg.show()
|
|
712
|
+
tseg.manage()
|
|
713
|
+
tseg.hide()
|
|
714
|
+
|
|
715
|
+
def toggle_collapsed(self, treeseg):
|
|
716
|
+
"""
|
|
717
|
+
Collapse/expand a tree.
|
|
718
|
+
"""
|
|
719
|
+
old_treeseg = treeseg
|
|
720
|
+
if old_treeseg['roof']:
|
|
721
|
+
new_treeseg = self._expanded_trees[self._keys[old_treeseg]]
|
|
722
|
+
else:
|
|
723
|
+
new_treeseg = self._collapsed_trees[self._keys[old_treeseg]]
|
|
724
|
+
|
|
725
|
+
# Replace the old tree with the new tree.
|
|
726
|
+
if old_treeseg.parent() is self:
|
|
727
|
+
self._remove_child_widget(old_treeseg)
|
|
728
|
+
self._add_child_widget(new_treeseg)
|
|
729
|
+
self._treeseg = new_treeseg
|
|
730
|
+
else:
|
|
731
|
+
old_treeseg.parent().replace_child(old_treeseg, new_treeseg)
|
|
732
|
+
|
|
733
|
+
# Move the new tree to where the old tree was. Show it first,
|
|
734
|
+
# so we can find its bounding box.
|
|
735
|
+
new_treeseg.show()
|
|
736
|
+
(newx, newy) = new_treeseg.label().bbox()[:2]
|
|
737
|
+
(oldx, oldy) = old_treeseg.label().bbox()[:2]
|
|
738
|
+
new_treeseg.move(oldx-newx, oldy-newy)
|
|
739
|
+
|
|
740
|
+
# Hide the old tree
|
|
741
|
+
old_treeseg.hide()
|
|
742
|
+
|
|
743
|
+
# We could do parent.manage() here instead, if we wanted.
|
|
744
|
+
new_treeseg.parent().update(new_treeseg)
|
|
745
|
+
|
|
746
|
+
##//////////////////////////////////////////////////////
|
|
747
|
+
## draw_trees
|
|
748
|
+
##//////////////////////////////////////////////////////
|
|
749
|
+
|
|
750
|
+
class TreeView(object):
|
|
751
|
+
def __init__(self, *trees):
|
|
752
|
+
from math import sqrt, ceil
|
|
753
|
+
|
|
754
|
+
self._trees = trees
|
|
755
|
+
|
|
756
|
+
self._top = Tk()
|
|
757
|
+
self._top.title('NLTK')
|
|
758
|
+
self._top.bind('<Control-x>', self.destroy)
|
|
759
|
+
self._top.bind('<Control-q>', self.destroy)
|
|
760
|
+
|
|
761
|
+
cf = self._cframe = CanvasFrame(self._top)
|
|
762
|
+
self._top.bind('<Control-p>', self._cframe.print_to_file)
|
|
763
|
+
|
|
764
|
+
# Size is variable.
|
|
765
|
+
self._size = IntVar(self._top)
|
|
766
|
+
self._size.set(12)
|
|
767
|
+
bold = ('helvetica', -self._size.get(), 'bold')
|
|
768
|
+
helv = ('helvetica', -self._size.get())
|
|
769
|
+
|
|
770
|
+
# Lay the trees out in a square.
|
|
771
|
+
self._width = int(ceil(sqrt(len(trees))))
|
|
772
|
+
self._widgets = []
|
|
773
|
+
for i in range(len(trees)):
|
|
774
|
+
widget = TreeWidget(cf.canvas(), trees[i], node_font=bold,
|
|
775
|
+
leaf_color='#008040', node_color='#004080',
|
|
776
|
+
roof_color='#004040', roof_fill='white',
|
|
777
|
+
line_color='#004040', draggable=1,
|
|
778
|
+
leaf_font=helv)
|
|
779
|
+
widget.bind_click_trees(widget.toggle_collapsed)
|
|
780
|
+
self._widgets.append(widget)
|
|
781
|
+
cf.add_widget(widget, 0, 0)
|
|
782
|
+
|
|
783
|
+
self._layout()
|
|
784
|
+
self._cframe.pack(expand=1, fill='both')
|
|
785
|
+
self._init_menubar()
|
|
786
|
+
|
|
787
|
+
def _layout(self):
|
|
788
|
+
i = x = y = ymax = 0
|
|
789
|
+
width = self._width
|
|
790
|
+
for i in range(len(self._widgets)):
|
|
791
|
+
widget = self._widgets[i]
|
|
792
|
+
(oldx, oldy) = widget.bbox()[:2]
|
|
793
|
+
if i % width == 0:
|
|
794
|
+
y = ymax
|
|
795
|
+
x = 0
|
|
796
|
+
widget.move(x-oldx, y-oldy)
|
|
797
|
+
x = widget.bbox()[2] + 10
|
|
798
|
+
ymax = max(ymax, widget.bbox()[3] + 10)
|
|
799
|
+
|
|
800
|
+
def _init_menubar(self):
|
|
801
|
+
menubar = Menu(self._top)
|
|
802
|
+
|
|
803
|
+
filemenu = Menu(menubar, tearoff=0)
|
|
804
|
+
filemenu.add_command(label='Print to Postscript', underline=0,
|
|
805
|
+
command=self._cframe.print_to_file,
|
|
806
|
+
accelerator='Ctrl-p')
|
|
807
|
+
filemenu.add_command(label='Exit', underline=1,
|
|
808
|
+
command=self.destroy, accelerator='Ctrl-x')
|
|
809
|
+
menubar.add_cascade(label='File', underline=0, menu=filemenu)
|
|
810
|
+
|
|
811
|
+
zoommenu = Menu(menubar, tearoff=0)
|
|
812
|
+
zoommenu.add_radiobutton(label='Tiny', variable=self._size,
|
|
813
|
+
underline=0, value=10, command=self.resize)
|
|
814
|
+
zoommenu.add_radiobutton(label='Small', variable=self._size,
|
|
815
|
+
underline=0, value=12, command=self.resize)
|
|
816
|
+
zoommenu.add_radiobutton(label='Medium', variable=self._size,
|
|
817
|
+
underline=0, value=14, command=self.resize)
|
|
818
|
+
zoommenu.add_radiobutton(label='Large', variable=self._size,
|
|
819
|
+
underline=0, value=28, command=self.resize)
|
|
820
|
+
zoommenu.add_radiobutton(label='Huge', variable=self._size,
|
|
821
|
+
underline=0, value=50, command=self.resize)
|
|
822
|
+
menubar.add_cascade(label='Zoom', underline=0, menu=zoommenu)
|
|
823
|
+
|
|
824
|
+
self._top.config(menu=menubar)
|
|
825
|
+
|
|
826
|
+
def resize(self, *e):
|
|
827
|
+
bold = ('helvetica', -self._size.get(), 'bold')
|
|
828
|
+
helv = ('helvetica', -self._size.get())
|
|
829
|
+
xspace = self._size.get()
|
|
830
|
+
yspace = self._size.get()
|
|
831
|
+
for widget in self._widgets:
|
|
832
|
+
widget['node_font'] = bold
|
|
833
|
+
widget['leaf_font'] = helv
|
|
834
|
+
widget['xspace'] = xspace
|
|
835
|
+
widget['yspace'] = yspace
|
|
836
|
+
if self._size.get() < 20: widget['line_width'] = 1
|
|
837
|
+
elif self._size.get() < 30: widget['line_width'] = 2
|
|
838
|
+
else: widget['line_width'] = 3
|
|
839
|
+
self._layout()
|
|
840
|
+
|
|
841
|
+
def destroy(self, *e):
|
|
842
|
+
if self._top is None: return
|
|
843
|
+
self._top.destroy()
|
|
844
|
+
self._top = None
|
|
845
|
+
|
|
846
|
+
def mainloop(self, *args, **kwargs):
|
|
847
|
+
"""
|
|
848
|
+
Enter the Tkinter mainloop. This function must be called if
|
|
849
|
+
this demo is created from a non-interactive program (e.g.
|
|
850
|
+
from a secript); otherwise, the demo will close as soon as
|
|
851
|
+
the script completes.
|
|
852
|
+
"""
|
|
853
|
+
if in_idle(): return
|
|
854
|
+
self._top.mainloop(*args, **kwargs)
|
|
855
|
+
|
|
856
|
+
def draw_trees(*trees):
|
|
857
|
+
"""
|
|
858
|
+
Open a new window containing a graphical diagram of the given
|
|
859
|
+
trees.
|
|
860
|
+
|
|
861
|
+
:rtype: None
|
|
862
|
+
"""
|
|
863
|
+
TreeView(*trees).mainloop()
|
|
864
|
+
return
|
|
865
|
+
|
|
866
|
+
##//////////////////////////////////////////////////////
|
|
867
|
+
## Demo Code
|
|
868
|
+
##//////////////////////////////////////////////////////
|
|
869
|
+
|
|
870
|
+
def demo():
|
|
871
|
+
import random
|
|
872
|
+
def fill(cw):
|
|
873
|
+
cw['fill'] = '#%06d' % random.randint(0,999999)
|
|
874
|
+
|
|
875
|
+
cf = CanvasFrame(width=550, height=450, closeenough=2)
|
|
876
|
+
|
|
877
|
+
t = Tree.fromstring('''
|
|
878
|
+
(S (NP the very big cat)
|
|
879
|
+
(VP (Adv sorta) (V saw) (NP (Det the) (N dog))))''')
|
|
880
|
+
|
|
881
|
+
tc = TreeWidget(cf.canvas(), t, draggable=1,
|
|
882
|
+
node_font=('helvetica', -14, 'bold'),
|
|
883
|
+
leaf_font=('helvetica', -12, 'italic'),
|
|
884
|
+
roof_fill='white', roof_color='black',
|
|
885
|
+
leaf_color='green4', node_color='blue2')
|
|
886
|
+
cf.add_widget(tc,10,10)
|
|
887
|
+
|
|
888
|
+
def boxit(canvas, text):
|
|
889
|
+
big = ('helvetica', -16, 'bold')
|
|
890
|
+
return BoxWidget(canvas, TextWidget(canvas, text,
|
|
891
|
+
font=big), fill='green')
|
|
892
|
+
def ovalit(canvas, text):
|
|
893
|
+
return OvalWidget(canvas, TextWidget(canvas, text),
|
|
894
|
+
fill='cyan')
|
|
895
|
+
|
|
896
|
+
treetok = Tree.fromstring('(S (NP this tree) (VP (V is) (AdjP shapeable)))')
|
|
897
|
+
tc2 = TreeWidget(cf.canvas(), treetok, boxit, ovalit, shapeable=1)
|
|
898
|
+
|
|
899
|
+
def color(node):
|
|
900
|
+
node['color'] = '#%04d00' % random.randint(0,9999)
|
|
901
|
+
def color2(treeseg):
|
|
902
|
+
treeseg.label()['fill'] = '#%06d' % random.randint(0,9999)
|
|
903
|
+
treeseg.label().child()['color'] = 'white'
|
|
904
|
+
|
|
905
|
+
tc.bind_click_trees(tc.toggle_collapsed)
|
|
906
|
+
tc2.bind_click_trees(tc2.toggle_collapsed)
|
|
907
|
+
tc.bind_click_nodes(color, 3)
|
|
908
|
+
tc2.expanded_tree(1).bind_click(color2, 3)
|
|
909
|
+
tc2.expanded_tree().bind_click(color2, 3)
|
|
910
|
+
|
|
911
|
+
paren = ParenWidget(cf.canvas(), tc2)
|
|
912
|
+
cf.add_widget(paren, tc.bbox()[2]+10, 10)
|
|
913
|
+
|
|
914
|
+
tree3 = Tree.fromstring('''
|
|
915
|
+
(S (NP this tree) (AUX was)
|
|
916
|
+
(VP (V built) (PP (P with) (NP (N tree_to_treesegment)))))''')
|
|
917
|
+
tc3 = tree_to_treesegment(cf.canvas(), tree3, tree_color='green4',
|
|
918
|
+
tree_xspace=2, tree_width=2)
|
|
919
|
+
tc3['draggable'] = 1
|
|
920
|
+
cf.add_widget(tc3, 10, tc.bbox()[3]+10)
|
|
921
|
+
|
|
922
|
+
def orientswitch(treewidget):
|
|
923
|
+
if treewidget['orientation'] == 'horizontal':
|
|
924
|
+
treewidget.expanded_tree(1,1).subtrees()[0].set_text('vertical')
|
|
925
|
+
treewidget.collapsed_tree(1,1).subtrees()[0].set_text('vertical')
|
|
926
|
+
treewidget.collapsed_tree(1).subtrees()[1].set_text('vertical')
|
|
927
|
+
treewidget.collapsed_tree().subtrees()[3].set_text('vertical')
|
|
928
|
+
treewidget['orientation'] = 'vertical'
|
|
929
|
+
else:
|
|
930
|
+
treewidget.expanded_tree(1,1).subtrees()[0].set_text('horizontal')
|
|
931
|
+
treewidget.collapsed_tree(1,1).subtrees()[0].set_text('horizontal')
|
|
932
|
+
treewidget.collapsed_tree(1).subtrees()[1].set_text('horizontal')
|
|
933
|
+
treewidget.collapsed_tree().subtrees()[3].set_text('horizontal')
|
|
934
|
+
treewidget['orientation'] = 'horizontal'
|
|
935
|
+
|
|
936
|
+
text = """
|
|
937
|
+
Try clicking, right clicking, and dragging
|
|
938
|
+
different elements of each of the trees.
|
|
939
|
+
The top-left tree is a TreeWidget built from
|
|
940
|
+
a Tree. The top-right is a TreeWidget built
|
|
941
|
+
from a Tree, using non-default widget
|
|
942
|
+
constructors for the nodes & leaves (BoxWidget
|
|
943
|
+
and OvalWidget). The bottom-left tree is
|
|
944
|
+
built from tree_to_treesegment."""
|
|
945
|
+
twidget = TextWidget(cf.canvas(), text.strip())
|
|
946
|
+
textbox = BoxWidget(cf.canvas(), twidget, fill='white', draggable=1)
|
|
947
|
+
cf.add_widget(textbox, tc3.bbox()[2]+10, tc2.bbox()[3]+10)
|
|
948
|
+
|
|
949
|
+
tree4 = Tree.fromstring('(S (NP this tree) (VP (V is) (Adj horizontal)))')
|
|
950
|
+
tc4 = TreeWidget(cf.canvas(), tree4, draggable=1,
|
|
951
|
+
line_color='brown2', roof_color='brown2',
|
|
952
|
+
node_font=('helvetica', -12, 'bold'),
|
|
953
|
+
node_color='brown4', orientation='horizontal')
|
|
954
|
+
tc4.manage()
|
|
955
|
+
cf.add_widget(tc4, tc3.bbox()[2]+10, textbox.bbox()[3]+10)
|
|
956
|
+
tc4.bind_click(orientswitch)
|
|
957
|
+
tc4.bind_click_trees(tc4.toggle_collapsed, 3)
|
|
958
|
+
|
|
959
|
+
# Run mainloop
|
|
960
|
+
cf.mainloop()
|
|
961
|
+
|
|
962
|
+
if __name__ == '__main__':
|
|
963
|
+
demo()
|