#!/usr/bin/env python
"""
parse mxnet output log into a markdown table
"""
import argparse
import sys
import re

parser = argparse.ArgumentParser(description='Parse mxnet output log')
parser.add_argument('logfile', nargs=1, type=str,
                    help = 'the log file for parsing')
parser.add_argument('--op', type=str, default='avg',
                    choices = ['avg', 'max'],
                    help = 'reduce operators for multiple machines')

args = parser.parse_args()

with open(args.logfile[0]) as f:
    lines = f.readlines()

res = [re.compile('.*Epoch\[(\d+)\] Train.*=([.\d]+)'),
       re.compile('.*Epoch\[(\d+)\] Valid.*=([.\d]+)'),
       re.compile('.*Epoch\[(\d+)\] Time.*=([.\d]+)')]

op = args.op

data = {}
for l in lines:
    i = 0
    for r in res:
        m = r.match(l)
        if m is not None:
            break
        i += 1
    if m is None:
        continue

    assert len(m.groups()) == 2
    epoch = int(m.groups()[0])
    val = float(m.groups()[1])

    if epoch not in data:
        data[epoch] = [0] * len(res) * 2

    if op == 'max' and i != 2:
        data[epoch][i*2] = max(val, data[epoch][i*2])
    else:
        data[epoch][i*2] += val
    data[epoch][i*2+1] += 1

print "| epoch | train accuracy | valid accuracy | time |"
print "| --- | --- | --- | --- |"

for k, v in data.items():
    if op == 'avg':
        print "| %d | %f | %f | %.1f |" % (k+1, v[0]/v[1], v[2]/v[3], v[4]/v[5])
    elif op == 'max':
        print "| %d | %f | %f | %.1f |" % (k+1, v[0], v[2], v[4]/v[5])

@@ -305,18 +305,22 @@
 ment('--
-op
+format
 ', type=
@@ -333,19 +333,24 @@
 efault='
-avg
+markdown
 ',%0A     
@@ -380,18 +380,24 @@
 = %5B'
-avg', 'max
+markdown', 'none
 '%5D,%0A
@@ -428,50 +428,42 @@
  = '
-reduce operators for multiple machines
+the format of the parsed outout
 ')%0A
-%0A
 args
@@ -718,22 +718,8 @@
 )%5D%0A%0A
-op = args.op%0A%0A
 data
@@ -1053,43 +1053,8 @@
  2%0A%0A
-    if op == 'max' and i != 2:%0A    
     
@@ -1074,51 +1074,15 @@
 *2%5D 
++
 = 
-max(val, data%5Bepoch%5D%5Bi*2%5D)%0A    else:%0A    
+val%0A
     
@@ -1100,46 +1100,52 @@
 %5Bi*2
++1
 %5D += 
-val%0A    data%5Bepoch%5D%5Bi*2+1%5D += 1%0A%0A
+1%0A%0Aif args.format == 'markdown':%0A    
 prin
@@ -1162,17 +1162,17 @@
  %7C train
- 
+-
 accuracy
@@ -1179,17 +1179,17 @@
  %7C valid
- 
+-
 accuracy
@@ -1199,16 +1199,20 @@
 time %7C%22%0A
+    
 print %22%7C
@@ -1237,17 +1237,20 @@
  --- %7C%22%0A
-%0A
+    
 for k, v
@@ -1271,28 +1271,8 @@
 ():%0A
-    if op == 'avg':%0A
     
@@ -1277,32 +1277,33 @@
       print %22%7C %25
+2
 d %7C %25f %7C %25f %7C %25.
@@ -1353,68 +1353,154 @@
 5%5D)%0A
-    
 elif 
-op == 'max':%0A        print %22%7C %25d %7C %25f %7C %25f %7C 
+args.format == 'none':%0A    print %22epoch%5Cttrain-accuracy%5Ctvalid-accuracy%5Cttime%22%0A    for k, v in data.items():%0A        print %22%252d%5Ct%25f%5Ct%25f%5Ct
 %25.1f
- %7C
 %22 %25 
@@ -1509,21 +1509,31 @@
 +1, v%5B0%5D
-, v%5B2
+/v%5B1%5D, v%5B2%5D/v%5B3
 %5D, v%5B4%5D/

update parse_log