Simon Clematide
Add morphological features toggle, hover tooltip, and UD documentation links
ae56e3f Download visualizer/ud_help.py from simon-clmtd/universal-dependencies-visualizer: direct link, hf CLI and curl.
- Browser
- Download file 5.8 kB
-
https://huggingface.co/spaces/simon-clmtd/universal-dependencies-visualizer/resolve/main/visualizer/ud_help.py
- Command line
-
hf download hf://spaces/simon-clmtd/universal-dependencies-visualizer/visualizer/ud_help.py
-
curl -L -o ud_help.py https://huggingface.co/spaces/simon-clmtd/universal-dependencies-visualizer/resolve/main/visualizer/ud_help.py
5.8 kB
| """Documentation links for the UPOS and basic dependency labels in a parse.""" | |
| import html | |
| POS_NAMES = { | |
| "ADJ": "Adjective", "ADP": "Adposition", "ADV": "Adverb", | |
| "AUX": "Auxiliary", "CCONJ": "Coordinating conjunction", "DET": "Determiner", | |
| "INTJ": "Interjection", "NOUN": "Noun", "NUM": "Numeral", "PART": "Particle", | |
| "PRON": "Pronoun", "PROPN": "Proper noun", "PUNCT": "Punctuation", | |
| "SCONJ": "Subordinating conjunction", "SYM": "Symbol", "VERB": "Verb", "X": "Other", | |
| } | |
| RELATION_NAMES = { | |
| "nsubj": "Nominal subject", "obj": "Object", "iobj": "Indirect object", | |
| "csubj": "Clausal subject", "ccomp": "Clausal complement", | |
| "xcomp": "Open clausal complement", "obl": "Oblique nominal", | |
| "vocative": "Vocative", "expl": "Expletive", "dislocated": "Dislocated element", | |
| "advcl": "Adverbial clause modifier", "advmod": "Adverbial modifier", | |
| "discourse": "Discourse element", "nmod": "Nominal modifier", | |
| "appos": "Appositional modifier", "nummod": "Numeric modifier", | |
| "acl": "Clausal modifier of a noun", "amod": "Adjectival modifier", | |
| "det": "Determiner", "clf": "Classifier", "case": "Case marking", | |
| "conj": "Conjunct", "cc": "Coordinating conjunction", | |
| "fixed": "Fixed multiword expression", "flat": "Flat multiword expression", | |
| "compound": "Compound", "list": "List", "parataxis": "Parataxis", | |
| "orphan": "Orphan", "goeswith": "Goes with", "reparandum": "Overridden disfluency", | |
| "punct": "Punctuation", "root": "Root", "dep": "Unspecified dependency", | |
| "aux": "Auxiliary", "cop": "Copula", "mark": "Marker", | |
| } | |
| # Verified universal subtype pages. Other subtypes link to their base relation | |
| # rather than assuming that a universal page exists for a language-specific label. | |
| SUBTYPE_NAMES = { | |
| "acl:relcl": "Relative clause modifier", "aux:pass": "Passive auxiliary", | |
| "csubj:pass": "Clausal passive subject", "nsubj:pass": "Passive nominal subject", | |
| "nmod:poss": "Possessive nominal modifier", | |
| } | |
| # Curated Universal Dependencies morphological features for English and German. | |
| FEATURE_NAMES = { | |
| # 1. Core morphological features | |
| "Case": "Case (e.g. nominative, accusative, dative, genitive)", | |
| "Gender": "Gender (masculine, feminine, neuter)", | |
| "Number": "Number (singular, plural)", | |
| "Person": "Person (first, second, third)", | |
| "Tense": "Tense (past, present, future)", | |
| "Mood": "Mood (indicative, imperative, subjunctive)", | |
| "VerbForm": "Verb form (finite, infinitive, participle, gerund)", | |
| "Degree": "Degree of comparison (positive, comparative, superlative)", | |
| # 2. Additional relevant features | |
| "PronType": "Pronominal type (personal, relative, demonstrative, etc.)", | |
| "Definite": "Definiteness (definite, indefinite)", | |
| "Poss": "Possessive marker/determiner", | |
| "Reflex": "Reflexive pronoun/marker", | |
| "NumType": "Numeral type (cardinal, ordinal, etc.)", | |
| "Voice": "Voice (active, passive)", | |
| "Aspect": "Aspect (aspectual distinctions)", | |
| "Polarity": "Polarity (positive, negative)", | |
| # 3. Other features worth knowing | |
| "Abbr": "Abbreviation", | |
| "Foreign": "Foreign word", | |
| "Typo": "Typographical error / unnormalized spelling", | |
| "ExtPos": "External part of speech", | |
| } | |
| def render_ud_help(conllu_text, word_links_html=""): | |
| """Render expanded Help with deduplicated labels used by visible word rows.""" | |
| pos, relations, features = set(), set(), set() | |
| for line in conllu_text.splitlines(): | |
| fields = line.split("\t") | |
| # The renderer excludes multiword headers and empty nodes by default. | |
| if len(fields) != 10 or not fields[0].isdigit(): | |
| continue | |
| if fields[3] in POS_NAMES: | |
| pos.add(fields[3]) | |
| if fields[7].split(":")[0] in RELATION_NAMES: | |
| relations.add(fields[7]) | |
| # FEATS is column 5 (0-indexed) | |
| feats_val = fields[5] | |
| if feats_val and feats_val != "_": | |
| for feat_pair in feats_val.split("|"): | |
| if "=" in feat_pair: | |
| feat_name = feat_pair.split("=")[0].strip() | |
| if feat_name in FEATURE_NAMES: | |
| features.add(feat_name) | |
| def link(label, name, path): | |
| return ( | |
| f'<li><a href="https://universaldependencies.org/u/{path}.html" ' | |
| f'target="_blank" rel="noopener noreferrer">{html.escape(label)}</a>' | |
| f' — {html.escape(name)}</li>' | |
| ) | |
| tags = "".join(link(tag, POS_NAMES[tag], "pos/" + tag) for tag in sorted(pos)) | |
| dependencies = [] | |
| for relation in sorted(relations): | |
| base = relation.split(":")[0] | |
| if relation in SUBTYPE_NAMES: | |
| name, page = SUBTYPE_NAMES[relation], relation.replace(":", "-") | |
| else: | |
| name, page = RELATION_NAMES[base], base | |
| if ":" in relation: | |
| name += " (subtype; link explains the base relation)" | |
| dependencies.append(link(relation, name, "dep/" + page)) | |
| feat_links = "".join( | |
| link(feat, FEATURE_NAMES[feat], "feat/" + feat) for feat in sorted(features) | |
| ) | |
| if not tags and not dependencies and not feat_links: | |
| return "" | |
| columns_html = "" | |
| if tags: | |
| columns_html += '<div><strong>POS tags in this sentence</strong><ul>' + tags + '</ul></div>' | |
| if dependencies: | |
| columns_html += '<div><strong>Relations in this sentence</strong><ul>' + "".join(dependencies) + '</ul></div>' | |
| if feat_links: | |
| columns_html += '<div><strong>Morphological features in this sentence</strong><ul>' + feat_links + '</ul></div>' | |
| if word_links_html: | |
| columns_html += word_links_html | |
| return ( | |
| '<details class="ud-help" open><summary>Help</summary>' | |
| f'<div class="ud-help-columns">{columns_html}</div></details>' | |
| ) | |