# (i,id) + { (i,) then (i+1,) } + { list [list1, ...] } # (i,) + { (i,) then (i+1,) } + { list [list1, ...] } # (i,id) + { (i,) then (0,) } + { float list } # (i,) + { (i,) then (0,) } + { float list } # (i,id) + { (i,) then (0,) } + { list [list1, ...] } # (i,) + { (i,) then (0,) } + { list [list1, ...] } # NOTES: # Legend is different for list versus [list1,...] # Plot should be discontinuous for (i,) then (0,) # parse file contents to get (i,id), cost, and parameters from mystic.munge import logfile_reader, read_raw_file try: step, param, cost = logfile_reader(filename) except SyntaxError: read_raw_file(filename) msg = "incompatible file format, try 'support_convergence.py'" raise SyntaxError(msg) # ignore everything after 'stop' step = step[:stop] cost = cost[:stop] param = param[:stop] # split (i,id) into iteration and id multinode = len(step[0]) - 1 #XXX: what if step = []? iter = [i[0] for i in step] if multinode: id = [i[1] for i in step] else: id = [0 for i in step]
def log_reader(filename, **kwds): """ plot parameter convergence from file written with 'LoggingMonitor' Available from the command shell as: mystic_log_reader.py filename [options] or as a function call as: mystic.log_reader(filename, **options) The option "param" takes an indicator string. The indicator string is built from comma-separated array slices. For example, params = ":" will plot all parameters. Alternatively, params = ":2, 3:" will plot all parameters except for the third parameter, while params = "0" will only plot the first parameter. Required Inputs: filename name of the convergence logfile (e.g log.txt) """ import shlex global __quit __quit = False instance = None # handle the special case where list is provided by sys.argv if isinstance(filename, (list, tuple)) and not kwds: cmdargs = filename # (above is used by script to parse command line) elif isinstance(filename, basestring) and not kwds: cmdargs = shlex.split(filename) # 'everything else' is essentially the functional interface else: cmdargs = kwds.get('kwds', '') if not cmdargs: out = kwds.get('out', None) dots = kwds.get('dots', False) line = kwds.get('line', False) iter = kwds.get('iter', None) legend = kwds.get('legend', False) nid = kwds.get('nid', None) param = kwds.get('param', None) # process "commandline" arguments cmdargs = '' cmdargs += '' if out is None else '--out={} '.format(out) cmdargs += '' if dots == False else '--dots ' cmdargs += '' if line == False else '--line ' cmdargs += '' if iter is None else '--iter={} '.format(iter) cmdargs += '' if legend == False else '--legend ' cmdargs += '' if nid is None else '--nid={} '.format(nid) cmdargs += '' if param is None else '--param="{}" '.format(param) else: cmdargs = ' ' + cmdargs if isinstance(filename, basestring): cmdargs = filename.split() + shlex.split(cmdargs) else: # special case of passing in monitor instance instance = filename cmdargs = shlex.split(cmdargs) #XXX: note that 'argparse' is new as of python2.7 from optparse import OptionParser def _exit(self, errno=None, msg=None): global __quit __quit = True if errno or msg: msg = msg.split(': error: ')[-1].strip() raise IOError(msg) OptionParser.exit = _exit parser = OptionParser(usage=log_reader.__doc__.split('\n\nOptions:')[0]) parser.add_option("-u","--out",action="store",dest="out",\ metavar="STR",default=None, help="filepath to save generated plot") parser.add_option("-d","--dots",action="store_true",dest="dots",\ default=False,help="show data points in plot") parser.add_option("-l","--line",action="store_true",dest="line",\ default=False,help="connect data points in plot with a line") parser.add_option("-i","--iter",action="store",dest="stop",metavar="INT",\ default=None,help="the largest iteration to plot") parser.add_option("-g","--legend",action="store_true",dest="legend",\ default=False,help="show the legend") parser.add_option("-n","--nid",action="store",dest="id",\ metavar="INT",default=None, help="id # of the nth simultaneous points to plot") parser.add_option("-p","--param",action="store",dest="param",\ metavar="STR",default=":", help="indicator string to select parameters") #parser.add_option("-f","--file",action="store",dest="filename",metavar="FILE",\ # default='log.txt',help="log file name") # import sys # if 'mystic_log_reader.py' not in sys.argv: from StringIO import StringIO f = StringIO() parser.print_help(file=f) f.seek(0) if 'Options:' not in log_reader.__doc__: log_reader.__doc__ += '\nOptions:%s' % f.read().split('Options:')[-1] f.close() try: parsed_opts, parsed_args = parser.parse_args(cmdargs) except UnboundLocalError: pass if __quit: return style = '-' # default linestyle if parsed_opts.dots: mark = 'o' # when using 'dots', also can turn off 'line' if not parsed_opts.line: style = 'None' else: mark = '' try: # get logfile name if instance: filename = instance else: filename = parsed_args[0] except: raise IOError("please provide log file name") try: # select which iteration to stop plotting at stop = int(parsed_opts.stop) except: stop = None try: # select which 'id' to plot results for runs = (int(parsed_opts.id), ) #XXX: allow selecting more than one id ? except: runs = None # i.e. 'all' **or** use id=0, which should be 'best' energy ? try: # select which parameters to plot select = parsed_opts.param.split(',') # format is ":2, 2:4, 5, 6:" except: select = [':'] # ensure all terms of select have a ":" for i in range(len(select)): if isinstance(select[i], int): select[i] = str(select[i]) if select[i] == '-1': select[i] = 'len(params)-1:len(params)' elif not select[i].count(':'): select[i] += ':' + str(int(select[i]) + 1) # == Possible results == # iter = (i,id) or (i,) # split => { (i,) then (i+1,) } or { (i,) then (0,) } # y x = { float list } or { list [list1, ...] } # == Use Cases == # (i,id) + { (i,) then (i+1,) } + { float list } # (i,) + { (i,) then (i+1,) } + { float list } # (i,id) + { (i,) then (i+1,) } + { list [list1, ...] } # (i,) + { (i,) then (i+1,) } + { list [list1, ...] } # (i,id) + { (i,) then (0,) } + { float list } # (i,) + { (i,) then (0,) } + { float list } # (i,id) + { (i,) then (0,) } + { list [list1, ...] } # (i,) + { (i,) then (0,) } + { list [list1, ...] } # NOTES: # Legend is different for list versus [list1,...] # Plot should be discontinuous for (i,) then (0,) # parse file contents to get (i,id), cost, and parameters try: instance = instance if instance else filename from mystic.munge import read_trajectories step, param, cost = read_trajectories(instance) except SyntaxError: from mystic.munge import read_raw_file read_raw_file(filename) msg = "incompatible file format, try 'support_convergence.py'" raise SyntaxError(msg) # ignore everything after 'stop' step = step[:stop] cost = cost[:stop] param = param[:stop] # split (i,id) into iteration and id multinode = len(step[0]) - 1 #XXX: what if step = []? iter = [i[0] for i in step] if multinode: id = [i[1] for i in step] else: id = [0 for i in step] # build the list of selected parameters params = range(len(param[0])) selected = [] for i in select: selected.extend(eval("params[%s]" % i)) selected = list(set(selected)) results = [[] for i in range(max(id) + 1)] # populate results for each id with the corresponding (iter,cost,param) for i in range(len(id)): if runs is None or id[i] in runs: # take only the selected 'id' results[id[i]].append((iter[i], cost[i], param[i])) # NOTE: for example... results = [[(0,...)],[(0,...),(1,...)],[],[(0,...)]] # build list of parameter (and cost) convergences for each id conv = [] cost_conv = [] iter_conv = [] for i in range(len(results)): conv.append([]) #; cost_conv.append([]); iter_conv.append([]) if len(results[i]): for k in range(len(results[i][0][2])): conv[i].append( [results[i][j][2][k] for j in range(len(results[i]))]) cost_conv.append( [results[i][j][1] for j in range(len(results[i]))]) iter_conv.append( [results[i][j][0] for j in range(len(results[i]))]) else: conv[i] = [[] for k in range(len(param[0]))] cost_conv.append([]) iter_conv.append([]) #print "iter_conv = %s" % iter_conv #print "cost_conv = %s" % cost_conv #print "conv = %s" % conv import matplotlib.pyplot as plt fig = plt.figure() #FIXME: These may fail when conv[i][j] = [[],[],[]] and cost = []. Verify this. ax1 = fig.add_subplot(2, 1, 1) for i in range(len(conv)): if runs is None or i in runs: # take only the selected 'id' for j in range(len(param[0])): if j in selected: # take only the selected 'params' tag = "%d,%d" % (j, i) # label is 'parameter,id' ax1.plot(iter_conv[i], conv[i][j], label="%s" % tag, marker=mark, linestyle=style) if parsed_opts.legend: plt.legend() ax2 = fig.add_subplot(2, 1, 2) for i in range(len(conv)): if runs is None or i in runs: # take only the selected 'id' tag = "%d" % i # label is 'cost id' ax2.plot(iter_conv[i], cost_conv[i], label='cost %s' % tag, marker=mark, linestyle=style) if parsed_opts.legend: plt.legend() if not parsed_opts.out: plt.show() else: fig.savefig(parsed_opts.out)
def log_reader(filename, **kwds): """ plot parameter convergence from file written with 'LoggingMonitor' Available from the command shell as: mystic_log_reader.py filename [options] or as a function call as: mystic.log_reader(filename, **options) The option "param" takes an indicator string. The indicator string is built from comma-separated array slices. For example, params = ":" will plot all parameters. Alternatively, params = ":2, 3:" will plot all parameters except for the third parameter, while params = "0" will only plot the first parameter. Required Inputs: filename name of the convergence logfile (e.g log.txt) """ import shlex try: basestring from StringIO import StringIO except NameError: basestring = str from io import StringIO global __quit __quit = False instance = None # handle the special case where list is provided by sys.argv if isinstance(filename, (list,tuple)) and not kwds: cmdargs = filename # (above is used by script to parse command line) elif isinstance(filename, basestring) and not kwds: cmdargs = shlex.split(filename) # 'everything else' is essentially the functional interface else: cmdargs = kwds.get('kwds', '') if not cmdargs: out = kwds.get('out', None) dots = kwds.get('dots', False) line = kwds.get('line', False) iter = kwds.get('iter', None) legend = kwds.get('legend', False) nid = kwds.get('nid', None) param = kwds.get('param', None) # process "commandline" arguments cmdargs = '' cmdargs += '' if out is None else '--out={} '.format(out) cmdargs += '' if dots == False else '--dots ' cmdargs += '' if line == False else '--line ' cmdargs += '' if iter is None else '--iter={} '.format(iter) cmdargs += '' if legend == False else '--legend ' cmdargs += '' if nid is None else '--nid={} '.format(nid) cmdargs += '' if param is None else '--param="{}" '.format(param) else: cmdargs = ' ' + cmdargs if isinstance(filename, basestring): cmdargs = filename.split() + shlex.split(cmdargs) else: # special case of passing in monitor instance instance = filename cmdargs = shlex.split(cmdargs) #XXX: note that 'argparse' is new as of python2.7 from optparse import OptionParser def _exit(self, errno=None, msg=None): global __quit __quit = True if errno or msg: msg = msg.split(': error: ')[-1].strip() raise IOError(msg) OptionParser.exit = _exit parser = OptionParser(usage=log_reader.__doc__.split('\n\nOptions:')[0]) parser.add_option("-u","--out",action="store",dest="out",\ metavar="STR",default=None, help="filepath to save generated plot") parser.add_option("-d","--dots",action="store_true",dest="dots",\ default=False,help="show data points in plot") parser.add_option("-l","--line",action="store_true",dest="line",\ default=False,help="connect data points in plot with a line") parser.add_option("-i","--iter",action="store",dest="stop",metavar="INT",\ default=None,help="the largest iteration to plot") parser.add_option("-g","--legend",action="store_true",dest="legend",\ default=False,help="show the legend") parser.add_option("-n","--nid",action="store",dest="id",\ metavar="INT",default=None, help="id # of the nth simultaneous points to plot") parser.add_option("-p","--param",action="store",dest="param",\ metavar="STR",default=":", help="indicator string to select parameters") #parser.add_option("-f","--file",action="store",dest="filename",metavar="FILE",\ # default='log.txt',help="log file name") # import sys # if 'mystic_log_reader.py' not in sys.argv: if PY3: f = StringIO() parser.print_help(file=f) f.seek(0) if 'Options:' not in log_reader.__doc__: log_reader.__doc__ += '\nOptions:%s' % f.read().split('Options:')[-1] f.close() else: if 'Options:' not in log_reader.__doc__: log_reader.__doc__ += '\nOptions:%s' % parser.format_help().split('Options:')[-1] try: parsed_opts, parsed_args = parser.parse_args(cmdargs) except UnboundLocalError: pass if __quit: return style = '-' # default linestyle if parsed_opts.dots: mark = 'o' # when using 'dots', also can turn off 'line' if not parsed_opts.line: style = 'None' else: mark = '' try: # get logfile name if instance: filename = instance else: filename = parsed_args[0] except: raise IOError("please provide log file name") try: # select which iteration to stop plotting at stop = int(parsed_opts.stop) except: stop = None try: # select which 'id' to plot results for runs = (int(parsed_opts.id),) #XXX: allow selecting more than one id ? except: runs = None # i.e. 'all' **or** use id=0, which should be 'best' energy ? try: # select which parameters to plot select = parsed_opts.param.split(',') # format is ":2, 2:4, 5, 6:" except: select = [':'] # ensure all terms of select have a ":" for i in range(len(select)): if isinstance(select[i], int): select[i] = str(select[i]) if select[i] == '-1': select[i] = 'len(params)-1:len(params)' elif not select[i].count(':'): select[i] += ':' + str(int(select[i])+1) # == Possible results == # iter = (i,id) or (i,) # split => { (i,) then (i+1,) } or { (i,) then (0,) } # y x = { float list } or { list [list1, ...] } # == Use Cases == # (i,id) + { (i,) then (i+1,) } + { float list } # (i,) + { (i,) then (i+1,) } + { float list } # (i,id) + { (i,) then (i+1,) } + { list [list1, ...] } # (i,) + { (i,) then (i+1,) } + { list [list1, ...] } # (i,id) + { (i,) then (0,) } + { float list } # (i,) + { (i,) then (0,) } + { float list } # (i,id) + { (i,) then (0,) } + { list [list1, ...] } # (i,) + { (i,) then (0,) } + { list [list1, ...] } # NOTES: # Legend is different for list versus [list1,...] # Plot should be discontinuous for (i,) then (0,) # parse file contents to get (i,id), cost, and parameters try: instance = instance if instance else filename from mystic.munge import read_trajectories step, param, cost = read_trajectories(instance) except SyntaxError: from mystic.munge import read_raw_file read_raw_file(filename) msg = "incompatible file format, try 'support_convergence.py'" raise SyntaxError(msg) # ignore everything after 'stop' step = step[:stop] cost = cost[:stop] param = param[:stop] # split (i,id) into iteration and id multinode = len(step[0]) - 1 #XXX: what if step = []? iter = [i[0] for i in step] if multinode: id = [i[1] for i in step] else: id = [0 for i in step] # build the list of selected parameters params = list(range(len(param[0]))) selected = [] locals = dict(params=params) for i in select: selected.extend(eval("params[%s]" % i, locals)) selected = list(set(selected)) results = [[] for i in range(max(id) + 1)] # populate results for each id with the corresponding (iter,cost,param) for i in range(len(id)): if runs is None or id[i] in runs: # take only the selected 'id' results[id[i]].append((iter[i],cost[i],param[i])) # NOTE: for example... results = [[(0,...)],[(0,...),(1,...)],[],[(0,...)]] # build list of parameter (and cost) convergences for each id conv = []; cost_conv = []; iter_conv = [] for i in range(len(results)): conv.append([])#; cost_conv.append([]); iter_conv.append([]) if len(results[i]): for k in range(len(results[i][0][2])): conv[i].append([results[i][j][2][k] for j in range(len(results[i]))]) cost_conv.append([results[i][j][1] for j in range(len(results[i]))]) iter_conv.append([results[i][j][0] for j in range(len(results[i]))]) else: conv[i] = [[] for k in range(len(param[0]))] cost_conv.append([]) iter_conv.append([]) #print("iter_conv = %s" % iter_conv) #print("cost_conv = %s" % cost_conv) #print("conv = %s" % conv) import matplotlib.pyplot as plt fig = plt.figure() #FIXME: These may fail when conv[i][j] = [[],[],[]] and cost = []. Verify this. ax1 = fig.add_subplot(2,1,1) for i in range(len(conv)): if runs is None or i in runs: # take only the selected 'id' for j in range(len(param[0])): if j in selected: # take only the selected 'params' tag = "%d,%d" % (j,i) # label is 'parameter,id' ax1.plot(iter_conv[i],conv[i][j],label="%s" % tag,marker=mark,linestyle=style) if parsed_opts.legend: plt.legend() ax2 = fig.add_subplot(2,1,2) for i in range(len(conv)): if runs is None or i in runs: # take only the selected 'id' tag = "%d" % i # label is 'cost id' ax2.plot(iter_conv[i],cost_conv[i],label='cost %s' % tag,marker=mark,linestyle=style) if parsed_opts.legend: plt.legend() if not parsed_opts.out: plt.show() else: fig.savefig(parsed_opts.out)