code: def hypercube_measures(filename, **kwds):
      """
      generate measure support plots from file written with ``write_support_file``
  
      Available from the command shell as::
  
          support_hypercube_measures filename [options]
  
      or as a function call::
  
          mystic.support.hypercube_measures(filename, **options)
  
      Args:
          filename (str): name of the convergence logfile (e.g ``paramlog.py``)
  
      Returns:
          None
  
      Notes:
          - The option *out* takes a string of the filepath for the generated plot.
            If ``out = True``, return the Figure object instead of generating a plot.
          - The options *bounds*, *axes*, *weight*, and *iters* all take indicator
            strings. The bounds should be given as comma-separated slices. For
            example, using ``bounds = "60:105, 0:30, 2.1:2.8"`` will set lower and
            upper bounds for x to be (60,105), y to be (0,30), and z to be (2.1,2.8).      Similarly, axes also accepts comma-separated groups of ints; however, for      axes, each entry indicates which parameters are to be plotted along each
            axis -- the first group for the x direction, the second for the y
            direction, and third for z. Thus, ``axes = "2 3, 6 7, 10 11"`` would set
            2nd and 3rd parameters along x. The corresponding weights are used to
            color the measure points, where 1.0 is black and 0.0 is white. For
            example, using ``weight = "0 1, 4 5, 8 9"`` would use the 0th and 1st
            parameters to weight x. Iters is also similar, however only accepts
            comma-separated ints. Hence, ``iters = "-1"`` will plot the last
            iteration, while ``iters = "0, 300, 700"`` will plot the 0th, 300th, and
            700th in three plots.
          - The option *label* takes comma-separated strings. Thus ``label = "x,y,"``      will place 'x' on the x-axis, 'y' on the y-axis, and nothing on the
            z-axis. LaTeX, such as ``label = "$ h $, $ a$, $ v$"`` will label the
            axes with standard LaTeX math formatting. Note that the leading space is
            required, while a trailing space aligns the text with the axis instead of      the plot frame.
          - The option *nid* takes an integer of the nth simultaneous points to plot.
          - The option *scale* takes an integer as a grayscale contrast multiplier.
          - The option *flat* takes a boolean, to plot results in a single plot.
  
      Warning:
          This function is intended to visualize weighted measures (i.e. weights
          and positions), where the weights must be normalized (to 1) or an error
          will be thrown."""
      import shlex
      from io import StringIO
  
      global __quit
      __quit = False
      _out = 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, str) 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)
              bounds = kwds.get("bounds", None)
              axes = kwds.get("axes", None)
              weight = kwds.get("weight", None)
              iters = kwds.get("iters", None)
              label = kwds.get("label", None)
              nid = kwds.get("nid", None)
              scale = kwds.get("scale", None)
              flat = kwds.get("flat", False)
  
              if isinstance(out, bool):
                  _out, out = out, None
  
              # process "commandline" arguments
              cmdargs = ""
              cmdargs += "" if out is None else "--out={} ".format(out)
              cmdargs += (
                  ""
                  if bounds is None
                  else '--bounds="{}" '.format(bounds)
              )
              cmdargs += (
                  "" if axes is None else '--axes="{}" '.format(axes)
              )
              cmdargs += (
                  ""
                  if weight is None
                  else '--weight="{}" '.format(weight)
              )
              cmdargs += (
                  "" if iters is None else '--iters="{}" '.format(iters)
              )
              cmdargs += (
                  "" if label is None else '--label="{}" '.format(label)
              )
              cmdargs += "" if nid is None else "--nid={} ".format(nid)
              cmdargs += (
                  "" if scale is None else "--scale={} ".format(scale)
              )
              cmdargs += "" if flat == False else "--flat "
          else:
              cmdargs = " " + cmdargs
          if isinstance(filename, str):
              cmdargs = filename.split() + shlex.split(cmdargs)
          else:  # special case of passing in monitor instance
              instance = filename
              cmdargs = shlex.split(cmdargs)
  
      # XXX: replace with 'argparse'?
      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=hypercube_measures.__doc__.split(NL2 + "Options:")[0]
      )
      parser.add_option(
          "-u",
          "--out",
          action="store",
          dest="out",
          metavar="STR",
          default=None,
          help="filepath to save generated plot",
      )
      parser.add_option(
          "-b",
          "--bounds",
          action="store",
          dest="bounds",
          metavar="STR",
          default="0:1, 0:1, 0:1",
          help="indicator string to set hypercube bounds",
      )
      parser.add_option(
          "-x",
          "--axes",
          action="store",
          dest="xyz",
          metavar="STR",
          default="1, 3, 5",
          help="indicator string to assign spatial parameter to axis",
      )
      parser.add_option(
          "-w",
          "--weight",
          action="store",
          dest="wxyz",
          metavar="STR",
          default="0, 2, 4",
          help="indicator string to assign weight parameter to axis",
      )
      parser.add_option(
          "-i",
          "--iters",
          action="store",
          dest="iters",
          metavar="STR",
          default="-1",
          help="indicator string to select iterations to plot",
      )
      parser.add_option(
          "-l",
          "--label",
          action="store",
          dest="label",
          metavar="STR",
          default=",,",
          help="string to assign label to axis",
      )
      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(
          "-s",
          "--scale",
          action="store",
          dest="scale",
          metavar="INT",
          default=1.0,
          help="grayscale contrast multiplier for points in plot",
      )
      parser.add_option(
          "-f",
          "--flat",
          action="store_true",
          dest="flatten",
          default=False,
          help="show selected iterations in a single plot",
      )
  
      f = StringIO()
      parser.print_help(file=f)
      f.seek(0)
      if "Options:" not in hypercube_measures.__doc__:
          hypercube_measures.__doc__ += NL + "Options:{0}".format(
              f.read().split("Options:")[-1]
          )
      f.close()
  
      try:
          parsed_opts, parsed_args = parser.parse_args(cmdargs)
      except UnboundLocalError:
          pass
      if __quit:
          return
  
      # get the name of the parameter log file
      if instance is None:
          instance = parsed_args[0]
      from mystic.munge import read_history
  
      params, _cost = read_history(instance, iter=False)
      # would be nice to use meta = ['wx','wx2','x','x2','wy',...]
      # exec "from {file} import meta".format(file=file)
  
      try:  # path of plot output file
          out = parsed_opts.out  # e.g. 'myplot.png'
          if "None" == out:
              out = None
      except:
          out = None
  
      try:  # select the bounds
          bounds = parsed_opts.bounds.split(
              ","
          )  # format is "60:105, 0:30, 2.1:2.8"
          bounds = [
              tuple(float(j) for j in i.split(":")) for i in bounds
          ]
      except:
          bounds = [(0, 1), (0, 1), (0, 1)]
  
      try:  # select which params are along which axes
          xyz = parsed_opts.xyz.split(",")  # format is "0 1, 4 5, 8 9"
          xyz = [tuple(int(j) for j in i.split()) for i in xyz]
      except:
          xyz = [(1,), (3,), (5,)]
  
      try:  # select which params are along which axes
          wxyz = parsed_opts.wxyz.split(
              ","
          )  # format is "0 1, 4 5, 8 9"
          wxyz = [tuple(int(j) for j in i.split()) for i in wxyz]
      except:
          wxyz = [(0,), (2,), (4,)]
  
      try:  # select labels for the axes
          label = parsed_opts.label.split(",")  # format is "x, y, z"
      except:
          label = ["", "", ""]
  
      x = params[max(xyz[0])]
      try:  # select which iterations to plot
          select = parsed_opts.iters.split(
              ","
          )  # format is "2, 4, 5, 6"
      except:
          select = ["-1"]
      # select = ['0','1','2','3']
  
      try:  # collapse non-consecutive iterations into a single plot...
          flatten = parsed_opts.flatten
      except:
          flatten = False
  
      try:  # select which 'id' to plot results for
          id = int(parsed_opts.id)
      except:
          id = None  # i.e. 'all' **or** use id=0, which should be 'best' energy ?
  
      try:  # scale the color in plotting the weights
          scale = float(parsed_opts.scale)
      except:
          scale = 1.0  # color = color**scale
  
      # ensure all terms of bounds and xyz are tuples
      for bound in bounds:
          if not isinstance(bound, tuple):
              raise TypeError(
                  "bounds should be tuples of (lower_bound,upper_bound)"
              )
      for i in range(len(xyz)):
          if isinstance(xyz[i], int):
              xyz[i] = (xyz[i],)
          elif not isinstance(xyz[i], tuple):
              raise TypeError(
                  "xyz should be tuples of (param1,param2,param3,...)"
              )
      for i in range(len(wxyz)):
          if isinstance(wxyz[i], int):
              wxyz[i] = (wxyz[i],)
          elif not isinstance(wxyz[i], tuple):
              raise TypeError(
                  "wxyz should be tuples of (param1,param2,param3,...)"
              )
  
      # ensure all terms of select are strings of ints
      for i in range(len(select)):
          if isinstance(select[i], int):
              select[i] = str(select[i])
          if select[i].count(":"):
              raise ValueError("iters should be ints")
      # if select[i] == '-1': select[i] = 'len(x)-1:len(x)'
      # elif not select[i].count(':'):
      #    select[i] += ':' + str(int(select[i])+1)
  
      # take only the selected 'id'
      if id != None:
          param = []
          for j in range(len(params)):
              param.append([p[id] for p in params[j]])
          params = param[:]
  
      # at this point, we should have:
      # bounds = [(60,105),(0,30),(2.1,2.8)] or [(None,None),(None,None),(None,None)]
      # xyz = [(2,3),(6,7),(10,11)] for any length tuple
      # wxyz = [(0,1),(4,5),(8,9)] for any length tuple (should match up with xyz)
      # select = ['-1'] or ['1','2','3','-1'] or similar
      # id = 0 or None
  
      plots = len(select)
      if not flatten:
          dim1, dim2 = best_dimensions(plots)
      else:
          dim1, dim2 = 1, 1
  
      # use the default bounds where not specified
      bounds = [list(i) for i in bounds]
      for i in range(len(bounds)):
          if bounds[i][0] is None:
              bounds[i][0] = 0
          if bounds[i][1] is None:
              bounds[i][1] = 1
  
      # correctly bound the first plot.  there must be at least one plot
      import matplotlib.pyplot as plt
  
      fig = plt.figure()
      try:
          Subplot3D = None
          ax1 = fig.add_subplot(dim1, dim2, 1, projection="3d")
          newsubplotcode = "ax = ax{0:d} = fig.add_subplot(dim1,dim2,{0:d}, projection='3d');"
      except:
          from mpl_toolkits.mplot3d import Axes3D as _Axes3D
          from matplotlib.axes import subplot_class_factory
  
          Subplot3D = subplot_class_factory(_Axes3D)
          ax1 = Subplot3D(fig, dim1, dim2, 1)
          newsubplotcode = (
              "ax = ax{0:d} = Subplot3D(fig, dim1,dim2,{0:d});"
          )
      ax1.plot([bounds[0][0]], [bounds[1][0]], [bounds[2][0]])
      ax1.plot([bounds[0][1]], [bounds[1][1]], [bounds[2][1]])
      globals = {
          "plt": plt,
          "fig": fig,
          "dim1": dim1,
          "dim2": dim2,
          "Subplot3D": Subplot3D,
          "bounds": bounds,
          "label": label,
      }
      if not flatten:
          code = "plt.title('iterations[{0}]');".format(select[0])
      else:
          code = "plt.title('iterations[*]');"
      code = compile(code, "<string>", "exec")
      exec(code, globals)
      ax1.set_xlabel(label[0])
      ax1.set_ylabel(label[1])
      ax1.set_zlabel(label[2])
      a = [ax1]
  
      # set up additional plots
      if not flatten:
          for i in range(2, plots + 1):
              code = newsubplotcode.format(i)
              code += "ax.plot([bounds[0][0]],[bounds[1][0]],[bounds[2][0]]);"
              code += "ax.plot([bounds[0][1]],[bounds[1][1]],[bounds[2][1]]);"
              code += "plt.title('iterations[{0}]');".format(
                  select[i - 1]
              )
              code += "ax.set_xlabel(label[0]);"
              code += "ax.set_ylabel(label[1]);"
              code += "ax.set_zlabel(label[2]);"
              code = compile(code, "<string>", "exec")
              exec(code, globals)
              a.append(globals["ax"])
  
      # turn each "n:m" in select to a list
      # _select = []
      # for sel in select:
      #    if sel[0] == ':': _select.append("0"+sel)
      #    else: _select.append(sel)
      # for i in range(len(_select)):
      #    if _select[i][-1] == ':': select[i] = _select[i]+str(len(x))
      #    else: select[i] = _select[i]
      # for i in range(len(select)):
      #    p = select[i].split(":")
      #    if p[0][0] == '-': p[0] = "len(x)"+p[0]
      #    if p[1][0] == '-': p[1] = "len(x)"+p[1]
      #    select[i] = p[0]+":"+p[1]
      # steps = [eval("range({0})".format(sel.replace(":",","))) for sel in select]
      locals = dict(x=x, params=params, wxyz=wxyz, xyz=xyz)
      steps = [eval("[int({0})]".format(sel), locals) for sel in select]
  
      # at this point, we should have:
      # xyz = [(2,3),(6,7),(10,11)] for any length tuple
      # wxyz = [(0,1),(4,5),(8,9)] for any length tuple (should match up with xyz)
      # steps = [[0],[1],[3],[8]] or similar
      if flatten:
          from mystic.tools import flatten
  
          steps = [list(flatten(steps))]
  
      # adjust for logarithmic scaling of intensity
      from numpy import e
  
      scale = e ** (scale - 1.0)
  
      # dot color is based on a product of weights
      t = []
      for v in range(len(steps)):
          t.append([])
          for s in steps[v]:
              for i in eval(
                  "[params[q][{0}] for q in wxyz[0]]".format(s), locals
              ):
                  for j in eval(
                      "[params[q][{0}] for q in wxyz[1]]".format(s),
                      locals,
                  ):
                      for k in eval(
                          "[params[q][{0}] for q in wxyz[2]]".format(s),
                          locals,
                      ):
                          t[v].append(
                              [
                                  str(
                                      (1.0 - i[q] * j[q] * k[q])
                                      ** scale
                                  )
                                  for q in range(len(i))
                              ]
                          )
                          if (
                              float(t[v][-1][-1]) > 1.0
                              or float(t[v][-1][-1]) < 0.0
                          ):
                              raise ValueError(
                                  "Weights must be in range 0-1. Check normalization and/or assignment."
                              )
  
      # build all the plots
      for v in range(len(steps)):
          for s in steps[v]:
              u = 0
              for i in eval(
                  "[params[q][{0}] for q in xyz[0]]".format(s), locals
              ):
                  for j in eval(
                      "[params[q][{0}] for q in xyz[1]]".format(s),
                      locals,
                  ):
                      for k in eval(
                          "[params[q][{0}] for q in xyz[2]]".format(s),
                          locals,
                      ):
                          for q in range(len(t[v][u])):
                              a[v].plot(
                                  [i[q]],
                                  [j[q]],
                                  [k[q]],
                                  marker="o",
                                  color=t[v][u][q],
                                  ms=10,
                              )
                          u += 1
  
      # process inputs
      if _out:
          out = _out
      if out:
          out = _out or out
  
      if not out:
          plt.show()
      elif out is True:
          return (
              fig  # XXX: better?: fig.axes if len(fig.axes) > 1 else ax
          )
      else:
          fig.savefig(out)
  
file_path: mystic/mystic/support.py
label_desc: Use image node_id 13 for calling a global function with example usage: hypercube_measures(filename) and returns: fig