summaryrefslogtreecommitdiff
path: root/python/pkg/cdec/sa/extract.py
blob: 472f128baf582e88484c62f9e6056122c0022a8f (plain)
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
#!/usr/bin/env python
import sys
import os
import argparse
import logging
import multiprocessing as mp
import signal
import cdec.sa

extractor, prefix = None, None
def make_extractor(config, grammars, features):
    global extractor, prefix
    signal.signal(signal.SIGINT, signal.SIG_IGN) # Let parent process catch Ctrl+C
    if features: load_features(features)
    extractor = cdec.sa.GrammarExtractor(config)
    prefix = grammars

def load_features(features):
    logging.info('Loading additional feature definitions from %s', features)
    prefix = os.path.dirname(features)
    sys.path.append(prefix)
    __import__(os.path.basename(features).replace('.py', ''))
    sys.path.remove(prefix)

def extract(inp):
    global extractor, prefix
    i, sentence = inp
    sentence = sentence[:-1]
    grammar_file = os.path.join(prefix, 'grammar.{0}'.format(i))
    with open(grammar_file, 'w') as output:
        for rule in extractor.grammar(sentence):
            output.write(str(rule)+'\n')
    grammar_file = os.path.abspath(grammar_file)
    return '<seg grammar="{0}" id="{1}">{2}</seg>'.format(grammar_file, i, sentence)

def main():
    logging.basicConfig(level=logging.INFO)
    parser = argparse.ArgumentParser(description='Extract grammars from a compiled corpus.')
    parser.add_argument('-c', '--config', required=True,
                        help='extractor configuration')
    parser.add_argument('-g', '--grammars', required=True,
                        help='grammar output path')
    parser.add_argument('-j', '--jobs', type=int, default=1,
                        help='number of parallel extractors')
    parser.add_argument('-s', '--chunksize', type=int, default=10,
                        help='number of sentences / chunk')
    parser.add_argument('-f', '--features', type=str, default=None,
                        help='additional feature definitions')
    args = parser.parse_args()

    if not os.path.exists(args.grammars):
        os.mkdir(args.grammars)
    if not (args.features is None or args.features.endswith('.py')):
        sys.stderr.write('Error: feature definition file should be a python module\n')
        sys.exit(1)
    
    if args.jobs > 1:
        logging.info('Starting %d workers; chunk size: %d', args.jobs, args.chunksize)
        pool = mp.Pool(args.jobs, make_extractor, (args.config, args.grammars, args.features))
        try:
            for output in pool.imap(extract, enumerate(sys.stdin), args.chunksize):
                print(output)
        except KeyboardInterrupt:
            pool.terminate()
    else:
        make_extractor(args.config, args.grammars, args.features)
        for output in map(extract, enumerate(sys.stdin)):
            print(output)

if __name__ == '__main__':
    main()