def hapiplot(*args, **kwargs): """Plot response from HAPI server. Demos ----- <https://github.com/hapi-server/client-python/blob/master/hapiclient/plot/hapiplot_test.py> Usage ----- data, meta = hapiplot(server, dataset, params, start, stop, **kwargs) or meta = hapiplot(data, meta, **kwargs) where data and meta are return values from `hapi()`. All parameters are plotted. If a parameter has a bins attribute, it is plotted using `heatmap()`. Otherwise, it is plotted using `timeseries()`. Returns ------- `data` is the same as that returned from `hapi()`. `meta` is the same as that returned from `hapi()` with the additon of meta['parameters'][i]['hapiplot']['figure'] is a reference to the figure (e.g., plt.gcf()). Usage example: >>> fig = meta['parameters'][i]['hapiplot']['figure'] >>> fig.set_facecolor('blue') >>> fig.axes[0].set_ylabel('new y-label') >>> fig.axes[0].set_title('new title\\nsubtitle\\nsubtitle') >>> fig.tight_layout() meta['parameters'][i]['hapiplot']['colorbar'] is a reference to the colorbar on the figure (if parameter plotted as a heatmap) meta['parameters'][i]['hapiplot']['image'] is PNG, PDF, or SVG data and is included only if `returnimage=True`. Usage example: >>> img = meta['parameters'][i]['hapiplot']['image'] >>> Image.open(io.BytesIO(img)).show() >>> # or >>> f = open('/tmp/a.png', 'wb') >>> f.write(img) >>> f.close() See Also --------- hapi: Get data from a HAPI server timeseries: Used by `hapiplot()` to HAPI parameters with no `bins` heatmap: Used by `hapiplot()` to HAPI parameters with `bins` <https://github.com/hapi-server/client-python-notebooks> kwargs ------ * logging: [False] Display console messages * usecache: [True] Use cached data * tsopts: {} kwargs for the `timeseries()` function * hmopts: {} kwargs for the `heatmap()` function Other kwargs ------------ * returnimage: [False] If True, `hapiplot()` returns binary image data * returnformat: [png], svg, or pdf * cachedir: Directory to store images. Default is hapiclient.hapi.cachedir() * useimagecache: [True] Used cached image (when returnimage=True) * saveimage: [False] Save image to `cachedir` * saveformat: [png], svg, or pdf Example -------- >>> server = 'http://hapi-server.org/servers/TestData/hapi' >>> dataset = 'dataset1' >>> start = '1970-01-01T00:00:00' >>> stop = '1970-01-02T00:00:00' >>> params = 'scalar,vector' >>> opts = {'logging': True} >>> >>> from hapiclient import hapiplot >>> hapiplot(server, dataset, params, start, stop, **opts) >>> >>> # or >>> >>> from hapiclient import hapi, hapiplot >>> data, meta = hapi(server, dataset, params, start, stop, **opts) >>> hapiplot(data, meta, **opts) """ if len(args) == 5: # For consistency with gallery and autoplot functions, allow useage of # hapiplot(server, dataset, parameters, start, stop, **kwargs) from hapiclient.hapi import hapiopts from hapiclient.hapi import hapi kwargs_allowed = hapiopts() kwargs_reduced = {} # Extract hapi() options from kwargs for key, value in kwargs.items(): if key in kwargs_allowed: kwargs_reduced[key] = value data, meta = hapi(args[0], args[1], args[2], args[3], args[4], **kwargs_reduced) meta = hapiplot(data, meta, **kwargs) return data, meta else: data = args[0] meta = args[1] # Default options opts = { 'logging': False, 'saveimage': False, 'returnimage': False, 'usecache': True, 'useimagecache': True, 'cachedir': cachedir(), 'backend': 'default', 'style': 'fast', 'title': '', 'ztitle': '', 'xlabel': '', 'ylabel': '', 'zlabel': '', 'logx': False, 'logy': False, 'logz': False, 'tsopts': {}, 'hmopts': {}, 'backend': 'default', 'rcParams': { 'savefig.dpi': 144, 'savefig.format': 'png', 'savefig.bbox': 'tight', 'savefig.transparent': False, 'figure.max_open_warning': 50, 'figure.figsize': (7, 3), 'figure.dpi': 144, 'axes.titlesize': 10, "font.family": "serif", "font.serif": rcParams['font.serif'], "font.weight": "normal" }, '_rcParams': { 'figure.bbox': 'standard' } } # Override defaults opts = setopts(opts, kwargs) from hapiclient import __version__ log('Running hapi.py version %s' % __version__, opts) # _rcParams are not actually rcParams: #'figure.bbox': 'standard', # Set to 'tight' to have fig.tight_layout() called before figure shown. if opts["saveimage"]: # Create cache directory dir = cachedir(opts['cachedir'], meta['x_server']) if not os.path.exists(dir): os.makedirs(dir) # Convert from NumPy array of byte literals to NumPy array of # datetime objects. timename = meta['parameters'][0]['name'] Time = hapitime2datetime(data[timename]) if len(meta["parameters"]) == 1: a = 0 # Time is only parameter else: a = 1 # Time plus another parameter for i in range(a, len(meta["parameters"])): meta["parameters"][i]['hapiplot'] = {} name = meta["parameters"][i]["name"] # Return cached image (case where we are returning binary image data) # imagepath() options. Only need filename under these conditions. if opts['saveimage'] or (opts['returnimage'] and opts['useimagecache']): # Will use given rc style parameters and style name to generate file name. # Assumes rc parameters of style and hapiplot defaults never change. styleParams = {} fmt = opts['rcParams']['savefig.format'] if 'rcParams' in kwargs: styleParams = kwargs['rcParams'] if 'savefig.format' in kwargs['rcParams']: kwargs['rcParams']['savefig.format'] fnameimg = imagepath(meta, i, opts['cachedir'], styleParams, fmt) if opts['useimagecache'] and opts['returnimage'] and os.path.isfile( fnameimg): log('Returning cached binary image data in ' + fnameimg, opts) meta["parameters"][i]['hapiplot']['imagefile'] = fnameimg with open(fnameimg, "rb") as f: meta["parameters"][i]['hapiplot']['image'] = f.read() continue name = meta["parameters"][i]["name"] log("Plotting parameter '%s'" % name, opts) if len(data[name].shape) > 3: # TODO: Implement more than 2 dimensions? warning( 'Parameter ' + name + ' has size with more than 2 dimensions. Plotting first two only.' ) continue # If parameter has a size with two elements, e.g., [N1, N2] # create N2 plots. if len(data[name].shape) == 3: # shape = (Time, N1, N2) nplts = data[name].shape[1] if opts['returnimage']: warning( 'Only returning first image for parameter with size[1] > 1.' ) nplts = 1 for j in range(nplts): timename = meta['parameters'][0]['name'] # Name to indicate what is plotted name_new = name + "[:," + str(j) + "]" # Reduced data ND Array datar = np.ndarray(shape=(data[name].shape[0]), dtype=[(timename, data.dtype[timename]), (name_new, data[name].dtype.str, data.dtype[name].shape[1])]) datar[timename] = data[timename] datar[name_new] = data[name][:, j] # Copy metadata to create a reduced metadata object metar = meta.copy() # Shallow copy metar["parameters"] = [] # Create parameters array with elements of Time parameter ... metar["parameters"].append(meta["parameters"][0]) # .... and this parameter metar["parameters"].append(meta["parameters"][i].copy()) # Give new name to indicate it is a subset of full parameter metar["parameters"][1]['name'] = name_new metar["parameters"][1]['name_orig'] = name # New size is N1 metar["parameters"][1]['size'] = [ meta["parameters"][i]['size'][1] ] if 'units' in metar["parameters"][1]: if type(meta["parameters"][i]['units'] ) == str or meta["parameters"][i]['units'] == None: # Same units applies to all dimensions metar["parameters"][1]["units"] = meta["parameters"][ i]['units'] else: metar["parameters"][1]["units"] = meta["parameters"][ i]['units'][j] if 'label' in metar["parameters"][1]: if type(meta["parameters"][i]['label']) == str: # Same label applies to all dimensions metar["parameters"][1]["label"] = meta["parameters"][ i]['label'] else: metar["parameters"][1]["label"] = meta["parameters"][ i]['label'][j] # Extract bins corresponding to jth column of data[name] if 'bins' in metar["parameters"][1]: metar["parameters"][1]['bins'] = [] metar["parameters"][1]['bins'].append( meta["parameters"][i]['bins'][j]) # rcParams is modified by setopts to have all rcParams. # reset to original passed rcParams so that imagepath # computes file name based on rcParams passed to hapiplot. if 'rcParams' in kwargs: opts['rcParams'] = kwargs['rcParams'] metar = hapiplot(datar, metar, **opts) meta["parameters"][i]['hapiplot'] = metar["parameters"][i][ 'hapiplot'] return meta if 'name_orig' in meta["parameters"][i]: title = meta["x_server"] + "\n" + meta["x_dataset"] + " | " + meta[ "parameters"][i]['name_orig'] else: title = meta["x_server"] + "\n" + meta["x_dataset"] + " | " + name as_heatmap = False if 'size' in meta['parameters'][ i] and meta['parameters'][i]['size'][0] > 10: as_heatmap = True if 'bins' in meta['parameters'][i]: as_heatmap = True if 'units' in meta["parameters"][i] and type( meta["parameters"][i]["units"]) == list: if as_heatmap: warning( "Not plotting %s as heatmap because components have different units." % meta["parameters"][i]["name"]) as_heatmap = False if as_heatmap: # Plot as heatmap hmopts = { 'returnimage': opts['returnimage'], 'transparent': opts['rcParams']['savefig.transparent'] } if meta["parameters"][i]["type"] == "string": warning( "Plots for only types double, integer, and isotime implemented. Not plotting %s." % meta["parameters"][i]["name"]) continue z = np.asarray(data[name]) if 'fill' in meta["parameters"][i] and meta["parameters"][i][ 'fill']: if meta["parameters"][i]["type"] == 'integer': z = z.astype('<f8', copy=False) z = fill2nan(z, meta["parameters"][i]['fill']) if 'bins' in meta['parameters'][i]: ylabel = meta["parameters"][i]['bins'][0]["name"] + " [" + meta[ "parameters"][i]['bins'][0]["units"] + "]" else: ylabel = "col %d" % i units = meta["parameters"][i]["units"] nl = "" if len(name) + len(units) > 30: nl = "\n" zlabel = name + nl + " [" + units + "]" if 'bins' in meta['parameters'][i]: if 'ranges' in meta["parameters"][i]['bins'][0]: bins = np.array(meta["parameters"][i]['bins'][0]["ranges"]) else: bins = np.array( meta["parameters"][i]['bins'][0]["centers"]) else: bins = np.arange(meta['parameters'][i]['size'][0]) dt = np.diff(Time) dtu = np.unique(dt) if len(dtu) > 1: #warning('Time values are not uniformly spaced. Bin width for ' # 'time will be based on time separation of consecutive time values.') if False and 'cadence' in meta: # Cadence != time bin width in general, so don't do this. # See https://github.com/hapi-server/data-specification/issues/75 # Kept for future reference when Parameter.bin.window or # Parameter.bin.windowWidth is added to spec. import isodate dt = isodate.parse_duration(meta['cadence']) if 'timeStampLocation' in meta: if meta['timeStampLocation'].lower() == "begin": Time = np.vstack((Time, Time + dt)) if meta['timeStampLocation'].lower() == "end": Time = np.vstack((Time - dt, Time)) if meta['timeStampLocation'].lower() == "center": Time = np.vstack((Time - dt / 2, Time + dt / 2)) else: # Default is center Time = np.vstack((Time - dt / 2, Time + dt / 2)) Time = np.transpose(Time) elif 'timeStampLocation' in meta: if meta['timeStampLocation'].lower() == "begin": Time = np.append(Time, Time[-1] + dtu[0]) if meta['timeStampLocation'].lower() == "end": Time = Time - dtu[0] Time = np.append(Time, Time[-1] + dtu[0]) if opts['xlabel'] != '' and 'xlabel' not in opts['hmopts']: hmopts['xlabel'] = opts['xlabel'] opts['hmopts']['ylabel'] = ylabel if opts['ylabel'] != '' and 'ylabel' not in opts['hmopts']: hmopts['ylabel'] = opts['ylabel'] opts['hmopts']['title'] = title if opts['title'] != '' and 'title' not in opts['hmopts']: hmopts['title'] = opts['title'] opts['hmopts']['zlabel'] = zlabel if opts['zlabel'] != '' and 'zlabel' not in opts['hmopts']: hmopts['zlabel'] = opts['zlabel'] if False: opts['hmopts']['ztitle'] = ztitle if opts['ztitle'] != '' and 'ztitle' not in opts['hmopts']: hmopts['ztitle'] = opts['ztitle'] if opts['logx'] is not False: hmopts['logx'] = True if opts['logy'] is not False: hmopts['logy'] = True if opts['logz'] is not False: hmopts['logz'] = True for key, value in opts['hmopts'].items(): hmopts[key] = value with rc_context(rc=opts['rcParams']): fig, cb = heatmap(Time, bins, np.transpose(z), **hmopts) meta["parameters"][i]['hapiplot']['figure'] = fig meta["parameters"][i]['hapiplot']['colorbar'] = cb else: tsopts = { 'logging': opts['logging'], 'returnimage': opts['returnimage'], 'transparent': opts['rcParams']['savefig.transparent'] } ptype = meta["parameters"][i]["type"] if ptype == "isotime": y = hapitime2datetime(data[name]) elif ptype == 'string': y = data[name].astype('U') else: y = np.asarray(data[name]) if 'fill' in meta["parameters"][i] and meta["parameters"][i][ 'fill']: if ptype == 'isotime' or ptype == 'string': Igood = y != meta["parameters"][i]['fill'] # Note that json reader returns fill to U not b. Nremoved = data[name].size - Igood.size if Nremoved > 0: # TODO: Implement masking so connected line plots will # show gaps as they do for NaN values. warning('Parameter ' + name + ' is of type ' + ptype + ' and has ' + str(Nremoved) + ' fill value(s). Masking is not implemented, ' 'so removing fill elements before plotting.') Time = Time[Igood] y = y[Igood] if ptype == 'integer': y = y.astype('<f8', copy=False) if ptype == 'integer' or ptype == 'double': y = fill2nan(y, meta["parameters"][i]['fill']) units = None if 'units' in meta["parameters"][i] and meta["parameters"][i][ 'units']: units = meta["parameters"][i]["units"] nl = "" if type(units) == str: if len(name) + len(units) > 30: nl = "\n" # TODO: Automatically figure out when this is needed. ylabel = name if units is not None and type(units) is not list: ylabel = name + nl + " [" + units + "]" if type(units) == list: ylabel = name if not 'legendlabels' in opts['tsopts']: legendlabels = [] if 'size' in meta['parameters'][i]: for l in range(0, meta['parameters'][i]['size'][0]): bin_label = '' bin_name = '' col_name = '' if 'bins' in meta['parameters'][i]: bin_name = meta['parameters'][i]['bins'][0]['name'] if 'label' in meta['parameters'][i]['bins'][0]: if type(meta['parameters'][i]['bins'][0] ['label']) == str: bin_name = meta['parameters'][i]['bins'][ 0]['label'] else: bin_name = meta['parameters'][i]['bins'][ 0]['label'][l] sep = '' if 'centers' in meta['parameters'][i]['bins'][ 0] and 'ranges' in meta['parameters'][i][ 'bins'][0]: bin_name = bin_name + ' bin with' sep = ';' bin_label = '' if 'units' in meta['parameters'][i]['bins'][0]: bin_units = meta['parameters'][i]['bins'][0][ 'units'] if type(bin_units) == list: if type(bin_units[l]) == str: bin_units = ' [' + bin_units[l] + ']' elif bin_units[l] == None: bin_units = ' []' else: bin_units = '' else: if type(bin_units) == str: bin_units = ' [' + bin_units + ']' else: bin_units = '' if 'centers' in meta['parameters'][i]['bins'][0]: if meta['parameters'][i]['bins'][0]['centers'][ l] is not None: bin_label = bin_label + ' center = ' + str( meta['parameters'][i]['bins'][0] ['centers'][l]) + bin_units else: bin_label = bin_label + ' center = None' if 'ranges' in meta['parameters'][i]['bins'][0]: if type(meta['parameters'][i]['bins'][0] ['ranges'][l]) == list: bin_label = bin_label + sep + ' range = [' + str( meta['parameters'][i]['bins'][0] ['ranges'][l][0]) + ', ' + str( meta['parameters'][i]['bins'][0] ['ranges'][l][1]) + ']' + bin_units else: bin_label = bin_label + sep + ' range = [None]' if bin_label != '': bin_label = 'bin:' + bin_label col_name = bin_name + '#%d' % l if col_name == '': col_name = 'col #%d' % l if 'label' in meta['parameters'][i]: #print(meta) #print(meta['parameters'][i]['label']) if type(meta['parameters'][i]['label']) == list: col_name = meta['parameters'][i]['label'][l] if type(units) == list: if len(units) == 1: legendlabels.append(col_name + ' [' + units[0] + '] ' + bin_label) elif type(units[l]) == str: legendlabels.append(col_name + ' [' + units[l] + '] ' + bin_label) elif units[l] == None: legendlabels.append(col_name + ' [] ' + bin_label) else: legendlabels.append(col_name + ' ' + bin_label) else: # Units are on y label legendlabels.append(col_name + ' ' + bin_label) tsopts['legendlabels'] = legendlabels # If xlabel in opts and opts['tsopts'], warn? if opts['xlabel'] != '' and 'xlabel' not in opts['tsopts']: tsopts['xlabel'] = opts['xlabel'] tsopts['ylabel'] = ylabel if opts['ylabel'] != '' and 'ylabel' not in opts['tsopts']: tsopts['ylabel'] = opts['ylabel'] tsopts['title'] = title if opts['title'] != '' and 'title' not in opts['tsopts']: tsopts['title'] = opts['title'] if opts['logx'] is not False and 'logx' not in opts['tsopts']: tsopts['logx'] = True if opts['logy'] is not False and 'logy' not in opts['tsopts']: tsopts['logy'] = True # Apply tsopts for key, value in opts['tsopts'].items(): tsopts[key] = value with rc_context(rc=opts['rcParams']): fig = timeseries(Time, y, **tsopts) meta["parameters"][i]['hapiplot']['figure'] = fig if opts['saveimage']: log('Writing %s' % fnameimg, opts) meta["parameters"][i]['hapiplot']['imagefile'] = fnameimg else: from io import BytesIO fnameimg = BytesIO() if opts['returnimage']: with rc_context(rc=opts['rcParams']): fig.canvas.print_figure(fnameimg) if opts['saveimage']: with open(fnameimg, mode='rb') as f: meta["parameters"][i]['hapiplot']['image'] = f.read() else: meta["parameters"][i]['hapiplot']['image'] = fnameimg.getvalue( ) else: with rc_context(rc=opts['rcParams']): fig.savefig(fnameimg) # Two calls to fig.tight_layout() may be needed b/c of bug in PyQt: # https://github.com/matplotlib/matplotlib/issues/10361 if opts['_rcParams']['figure.bbox'] == 'tight': fig.tight_layout() return meta
def autoplot(server, dataset, parameters, start, stop, **kwargs): """Plot data from a HAPI server using Autoplot. If not found, autoplot.jar is downloaded an launched. If found, autoplot.jar is updated if server version is newer than cached version. Example ------- >>> from hapiclient import autoplot >>> server = 'http://hapi-server.org/servers/TestData2.0/hapi' >>> autoplot(server, 'dataset1', 'scalar,vector', '1970-01-01', '1970-01-02') Autoplot application launches or its canvas is updated. The options are the same as that for `hapiplot` with the addition of the kwargs stack : bool [False] Create a stack plot of parameters. port : int [8079] The port number to use to connect to Autoplot. version : string ['devel'] The version of Autoplot to use. Can be a version string, e.g., 'v2018a_11', 'devel', 'latest', or 'nightly'. See <http://autoplot.org/developer#Development_Versions> for a description of the difference between versions. """ import os import re import platform import subprocess from hapiclient.util import setopts, log, urlopen, urlretrieve, urlquote from hapiclient.hapi import cachedir opts = { 'logging': False, 'cache': True, 'cachedir': cachedir(), 'usecache': False, 'newwindow': False, 'version': 'devel', 'port': 8079 } # Override defaults opts = setopts(opts, kwargs) autoplotserver = "http://localhost:" + str(opts['port']) + "/" url = server + "?id=" + dataset + "¶meters=" + parameters url = url + "&timerange=" + start + "/" + stop serverrunning = False try: # See if server needs to be started. if opts['logging']: log('Trying test. Requesting ' + autoplotserver, opts) f = urlopen(autoplotserver) res = f.read().decode('utf-8') if res.startswith('OK'): log('Server running.', opts) serverrunning = True else: log('Server responding but with wrong response to test.', opts) f.close() except: log('Server not running. Will start server.', opts) print(url) if serverrunning: # Send request to update GUI. try: # This won't detect if the version requested matches # the version running. rurl = autoplotserver + "?uri=" + urlquote("vap+hapi:" + url) if opts['logging']: print("autoplot(): Requesting " + rurl) log('Autoplot GUI should be updating.', opts) f = urlopen(rurl) res = f.read().decode('utf-8') if res.startswith('OK'): log('Request successful. Autoplot GUI updated.', opts) f.close() return else: f.close() log('Request unsuccessful.', opts) serverrunning = False except Exception as e: print(e) # Request was sent, so return. if serverrunning == True: return if opts['version'] == 'nightly': jarurl = 'https://ci-pw.physics.uiowa.edu/job/autoplot-release/lastSuccessfulBuild/artifact/autoplot/Autoplot/dist/autoplot.jar' elif opts['version'] == 'devel': jarurl = 'http://autoplot.org/jnlp/devel/autoplot.jar' elif opts['version'].startswith('v'): jarurl = 'http://autoplot.org/jnlp/' + opts['version'] + '/autoplot.jar' else: opts['version'] = 'latest' jarurl = 'http://autoplot.org/jnlp/latest/autoplot.jar' try: result = subprocess.check_output('java -version', shell=True, stderr=subprocess.STDOUT) version = re.sub(r'.*"(.*)".*', r'\1', result.decode().split('\n')[0]) log("Java version: " + version, opts) except: # TODO: Automatically download and extract from https://jdk.java.net/14/? log( "Java is required. See https://www.java.com/en/download/ or https://jdk.java.net/14/", opts) return jydir = os.path.dirname(os.path.realpath(__file__)) jarpath = os.path.join(opts['cachedir'], 'jar/autoplot-' + opts['version'] + '.jar') jaricon = os.path.join(jydir, 'autoplot.png') # Download jar file if needed. log('Checking if autoplot.jar needs to be downloaded or updated.', opts) urlretrieve(jarurl, jarpath, check_last_modified=True, **opts) #download(jarpath, jarurl, **opts) com = "java" if 'darwin' in platform.platform().lower(): com = com + " -Xdock:icon=" + jaricon com = com + ' -Xdock:name="Autoplot"' com = com + " -DPORT=" + str(opts['port']) com = com + " -DHAPI_DATA=" + opts['cachedir'] com = com + " -DhapiServerCache=true" com = com + " -jar " + jarpath com = com + " --noAskParams" com = com + " '" + os.path.join(jydir, 'server.jy?uri=') com = com + urlquote("vap+hapi:" + url) + "'" com = com + " &" if opts['logging']: log("Executing " + com, opts) os.system(com)
def gallery(*args, **kwargs): """Create a web-browsable gallery of plots (aka "PNG Walk"). Experimental code. Requires hapiplotserver. Use pip install 'git+https://github.com/hapi-server/plotserver-python' For additional documentation and demonstration, see hapi_demo.ipynb at <https://github.com/hapi-server/client-python-notebooks/> Usage ---------- gallery(server, dataset) gallery(server, dataset, parameter) Examples ---------- >>> from hapiclient import gallery >>> gallery('http://hapi-server.org/servers/TestData/hapi', 'dataset1') # Webpage tab opens >>> from hapiclient import gallery >>> gallery('http://hapi-server.org/servers/TestData/hapi','dataset1', 'vector') # Webpage tab opens Parameters ---------- server : str A URL for a HAPI-compliant server. (A HAPI URL always ends with "/hapi".) dataset : str A dataset from a HAPI server. The valid datasets can be determined using `hapi(server)`. parameter : str A parameter in dataset. The valid parameters can be determined using `hapi(server, dataset)`. Returns ---------- None (a new tab is opened in the user's default browser) """ import time import webbrowser from multiprocessing import Process from hapiclient.hapi import cachedir from hapiclient.util import error, warning, setopts, prompt from hapiplotserver import hapiplotserver if len(args) != 2 and len(args) != 3: error('Number of arguments must be 2 or 3. See help(gallery).') server = args[0] dataset = args[1] if len(args) == 3: parameters = args[2].split(",") else: parameters = [''] if len(parameters) > 1: # Eventually, mulitple parameters will result is a stack plot. warning('Multiple parameters given; only first will be shown.') parameters = parameters[0] if not all(type(arg) is str for arg in args): error('All inputs must be a strings. See help(gallery).') # Default options opts = { 'cache_dir': cachedir(), 'usecache': True, 'port': 5002, 'format': 'png', 'figsize': (7, 3), 'dpi': 144, 'transparent': True, 'loglevel': 'default' } # Override defaults opts = setopts(opts, kwargs) if not parameters == '': paramopt = "¶meters=" + parameters else: paramopt = '' url = 'http://127.0.0.1:' + str(opts['port']) url = url + '/?server=' + server url = url + '&id=' + dataset url = url + paramopt url = url + '&format=gallery' try: process = Process(target=hapiplotserver, kwargs=opts) process.start() except Exception as e: print(e) print("Terminating server.") process.terminate() print(" * Opening ViViz in browser in 1 second.") time.sleep(1) webbrowser.open(url, new=2) prompt( "\n\033[0;34mPress a key at any time to terminate ViViz gallery server.\033[0m\n\n" ) process.terminate() print("ViViz gallery server has terminated.")