convertinput.py
8.94 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
'''
Created on Oct 23, 2013
@author: mlenart
'''
import logging
from common import Interpretation4Analyzer
from morfeuszbuilder.fsa.common import Interpretation4Generator
#from morfeuszbuilder.fsa import externalsort
def _mergeEntries(inputLines, lowercase):
prevKey = None
prevInterps = None
for key, interp in inputLines:
key = key.lower() if lowercase else key
# print 'key=', key, 'interp=', interp
# if not key:
# print 'key=', key, 'interp=', interp
# assert key
assert key
if prevKey and prevKey == key:
prevInterps.append(interp)
else:
if prevKey:
yield (prevKey, frozenset(prevInterps))
prevKey = key
prevInterps = [interp]
if prevInterps:
yield (prevKey, frozenset(prevInterps))
def parseLine(line):
splitLine = line.strip().split(u'\t')
if len(splitLine) == 5:
orth, base, tag, name, qualifier = splitLine
elif len(splitLine) == 4:
orth, base, tag, name = splitLine
qualifier = ''
elif len(splitLine) == 3:
orth, base, tag = splitLine
name = ''
qualifier = ''
else:
raise ValueError('input line "%s" does not have 3, 4 or 5 tab-separated fields' % line)
return orth, base, tag, name, qualifier
class PolimorfConverter4Analyzer(object):
def __init__(self, tagset, namesMap, qualifiersMap, encoder, inputEncoding, segmentRulesManager):
self.tagset = tagset
self.namesMap = namesMap
self.qualifiersMap = qualifiersMap
self.encoder = encoder
self.inputEncoding = inputEncoding
self.segmentRulesManager = segmentRulesManager
# we do it the ugly way (parse to plain text) because it is way more memory-efficient
def _partiallyParseLines(self, inputLines):
for line in inputLines:
line = line.decode(self.inputEncoding).strip('\n')
if line:
orth, base, tag, name, qualifier = parseLine(line)
tagnum = self.tagset.getTagnum4Tag(tag)
namenum = self.namesMap[name]
typenum = self.segmentRulesManager.lexeme2SegmentTypeNum(base, tagnum)
qualifiers = qualifier.split('|') if qualifier else frozenset([u''])
qualsnum = self.qualifiersMap[frozenset(qualifiers)]
assert not (
self.segmentRulesManager.shiftOrthMagic.shouldReplaceLemmaWithOrth(typenum)
and self.segmentRulesManager.shiftOrthMagic.getNewSegnum4ShiftOrth(typenum) != None)
if self.segmentRulesManager.shiftOrthMagic.shouldReplaceLemmaWithOrth(typenum):
# print 'replace %s %s %s %d with %s %s %s %d' % (orth, base, tag, typenum, orth, orth, tag, typenum)
base = orth
yield '\t'.join((
orth.encode(self.inputEncoding),
base.encode(self.inputEncoding),
str(tagnum),
str(namenum),
str(typenum),
str(qualsnum)))
if self.segmentRulesManager.shiftOrthMagic.getNewSegnum4ShiftOrth(typenum) != None:
# print 'add to existing %s %s %s %d also this: %s %s %s %d' % (orth, base, tag, typenum, orth, orth, tag, self.segmentRulesManager.shiftOrthMagic.getNewSegnum4ShiftOrth(typenum))
base = orth
typenum = self.segmentRulesManager.shiftOrthMagic.getNewSegnum4ShiftOrth(typenum)
yield '\t'.join((
orth.encode(self.inputEncoding),
base.encode(self.inputEncoding),
str(tagnum),
str(namenum),
str(typenum),
str(qualsnum)))
# input lines are encoded and partially parsed
def _sortLines(self, inputLines):
return sorted(inputLines, key=lambda line: self.encoder.word2SortKey(line.split('\t')[0].decode('utf8')))
# return sorted(inputLines, key=lambda line: self.encoder.word2SortKey(line.split('\t')[0].decode('utf8')))
def _reallyParseLines(self, inputLines):
for line in inputLines:
line = line.decode(self.inputEncoding).strip(u'\n')
if line:
orth, base, tagnum, namenum, typenum, qualsnum = line.split(u'\t')
tagnum = int(tagnum)
namenum = int(namenum)
typenum = int(typenum)
#~ qualifiers = qualifierStr.split('|') if qualifierStr else []
qualsnum = int(qualsnum)
yield (orth, Interpretation4Analyzer(orth, base, tagnum, namenum, typenum, qualsnum))
def convert(self, inputLines):
return _mergeEntries(self._reallyParseLines(self._sortLines(self._partiallyParseLines(inputLines))), lowercase=True)
class PolimorfConverter4Generator(object):
def __init__(self, tagset, namesMap, qualifiersMap, encoder, inputEncoding, segmentRulesManager):
self.tagset = tagset
self.namesMap = namesMap
self.qualifiersMap = qualifiersMap
self.encoder = encoder
self.inputEncoding = inputEncoding
self.segmentRulesManager = segmentRulesManager
# we do it the ugly way (parse to plain text) because it is way more memory-efficient
def _partiallyParseLines(self, inputLines):
for line in inputLines:
line = line.decode(self.inputEncoding).strip('\n')
if line:
orth, base, tag, name, qualifier = parseLine(line)
if base:
homonymId = u''
if u':' in base:
assumedBase, assumedHomonymId = base.split(u':', 1)
if assumedBase != u'' and assumedHomonymId != u'' and assumedHomonymId.isalnum():
base, homonymId = assumedBase, assumedHomonymId
tagnum = self.tagset.getTagnum4Tag(tag)
namenum = self.namesMap[name]
qualifiers = qualifier.split('|') if qualifier else frozenset([u''])
qualsnum = self.qualifiersMap[frozenset(qualifiers)]
typenum = self.segmentRulesManager.lexeme2SegmentTypeNum(base, tagnum)
if self.segmentRulesManager.shiftOrthMagic.shouldReplaceLemmaWithOrth(typenum):
# print 'replace %s %s %s %d with %s %s %s %d' % (orth, base, tag, typenum, orth, orth, tag, typenum)
base = orth
yield '\t'.join((
orth.encode(self.inputEncoding),
base.encode(self.inputEncoding),
str(tagnum),
str(namenum),
str(typenum),
homonymId.encode(self.inputEncoding),
str(qualsnum)))
if self.segmentRulesManager.shiftOrthMagic.getNewSegnum4ShiftOrth(typenum) != None:
base = orth
typenum = self.segmentRulesManager.shiftOrthMagic.getNewSegnum4ShiftOrth(typenum)
yield '\t'.join((
orth.encode(self.inputEncoding),
base.encode(self.inputEncoding),
str(tagnum),
str(namenum),
str(typenum),
homonymId.encode(self.inputEncoding),
str(qualsnum)))
else:
logging.warn('Ignoring line: "%s" - contains empty lemma', line.strip())
# input lines are encoded and partially parsed
def _sortLines(self, inputLines):
return sorted(inputLines, key=lambda line: (self.encoder.word2SortKey(line.split('\t')[1].decode('utf8')), line))
def _reallyParseLines(self, inputLines):
prevLine = None
for line in inputLines:
line = line.decode(self.inputEncoding).strip(u'\n')
if line and line != prevLine:
orth, base, tagnum, namenum, typenum, homonymId, qualsnum = line.split(u'\t')
# print orth.encode('utf8'), base.encode('utf8'), homonymId
tagnum = int(tagnum)
namenum = int(namenum)
typenum = int(typenum)
del prevLine
prevLine = line
qualsnum = int(qualsnum)
#~ qualifiers = qualifierStr.split('|') if qualifierStr else ()
yield (base, Interpretation4Generator(orth, base, tagnum, namenum, typenum, homonymId, qualsnum))
def convert(self, inputLines):
return _mergeEntries(self._reallyParseLines(self._sortLines(self._partiallyParseLines(inputLines))), lowercase=False)