def _match_error_to_data_set(x, ex): """ Inflates ex to match the dimensionality of x, "intelligently". x is assumed to be a 2D array. """ # Simplest case, ex is None or a number if not _fun.is_iterable(ex): # Just make a matched list of Nones if ex is None: ex = [ex] * len(x) # Make arrays of numbers if _fun.is_a_number(ex): value = ex # temporary storage ex = [] for n in range(len(x)): ex.append([value] * len(x[n])) # Otherwise, ex is iterable # Default behavior: If the elements are all numbers and the length matches # that of the first x-array, assume this is meant to match all the x # data sets if _fun.elements_are_numbers(ex) and len(ex) == len(x[0]): ex = [ex] * len(x) # The user may specify a list of some iterable and some not. Assume # in this case that at least the lists are the same length for n in range(len(x)): # do nothing to the None's # Inflate single numbers to match if _fun.is_a_number(ex[n]): ex[n] = [ex[n]] * len(x[n]) return ex
def _match_error_to_data_set(x, ex): """ Inflates ex to match the dimensionality of x, "intelligently". x is assumed to be a 2D array. """ # Simplest case, ex is None or a number if not _fun.is_iterable(ex): # Just make a matched list of Nones if ex is None: ex = [ex]*len(x) # Make arrays of numbers if _fun.is_a_number(ex): value = ex # temporary storage ex = [] for n in range(len(x)): ex.append([value]*len(x[n])) # At this point, ex is iterable # Default behavior: If the elements are all numbers and the length matches # that of the first x-array, assume this is meant to match all the x # data sets if _fun.elements_are_numbers(ex) and len(ex) == len(x[0]): ex = [ex]*len(x) # Make sure it's a list (for appending) if not type(ex) == list: ex = list(ex) # The user may specify a list of some iterable and some not. # The list length may not match while len(ex) < len(x): ex.append(ex[-1]) # Now they are the same length for n in range(len(x)): # do nothing to the None's # Inflate single numbers to match if _fun.is_a_number(ex[n]): ex[n] = [ex[n]]*len(x[n]) return ex
def xy_data(xdata, ydata, eydata=None, exdata=None, label=None, xlabel='', ylabel='', \ title='', shell_history=1, xshift=0, yshift=0, xshift_every=1, yshift_every=1, \ coarsen=0, style=None, clear=True, axes=None, xscale='linear', yscale='linear', grid=False, \ legend='best', legend_max=20, autoformat=True, tall=False, draw=True, **kwargs): """ Plots specified data. xdata, ydata Arrays (or arrays of arrays) of data to plot eydata, exdata Arrays of x and y errorbar values label string or array of strings for the line labels xlabel='' label for the x-axis ylabel='' label for the y-axis title='' title for the axes; set to None to have nothing. shell_history=1 how many commands from the pyshell history to include with the title xshift=0, yshift=0 progressive shifts on the data, to make waterfall plots xshift_every=1 perform the progressive shift every 1 or n'th line. yshift_every=1 perform the progressive shift every 1 or n'th line. style style cycle object. clear=True if no axes are specified, clear the figure, otherwise clear just the axes. axes=None which axes to use, or "gca" for the current axes xscale,yscale 'linear' by default. Set either to 'log' for log axes grid=False Should we draw a grid on the axes? legend='best' where to place the legend (see pylab.legend()) Set this to None to ignore the legend. legend_max=20 number of legend entries before it's truncated with '...' autoformat=True Should we format the figure for printing? False Should the format be tall? draw=True whether or not to draw the plot after plotting **kwargs are sent to pylab.errorbar() """ _pylab.ioff() # make sure everything is at least iterable. if not _fun.is_iterable(xdata): xdata = [xdata] if not _fun.is_iterable(exdata): exdata = [exdata] if not _fun.is_iterable(ydata): ydata = [ydata] if not _fun.is_iterable(eydata): eydata = [eydata] # make sure at least xdata and ydata are 2-D if _fun.is_a_number(xdata[0]): xdata = [xdata] if _fun.is_a_number(ydata[0]): ydata = [ydata] # make sure the number of data sets agrees N = max(len(xdata), len(ydata)) for n in range(N - len(xdata)): xdata.append(xdata[0]) for n in range(N - len(ydata)): ydata.append(ydata[0]) for n in range(N - len(exdata)): exdata.append(exdata[0]) for n in range(N - len(eydata)): eydata.append(eydata[0]) # loop over each x and y data set, making sure None's are all converted # to counting arrays for n in range(N): # clean up the [None]'s if _fun.is_iterable(xdata[n]) and xdata[n][0] == None: xdata[n] = None if _fun.is_iterable(ydata[n]) and ydata[n][0] == None: ydata[n] = None if xdata[n] == None and ydata[n] == None: print "ERROR: " + str(n) + "'th data set is (None, None)." return if xdata[n] == None: xdata[n] = _n.arange(len(ydata[n])) if ydata[n] == None: ydata[n] = _n.arange(len(xdata[n])) # check that the labels is a list of strings of the same length if not _fun.is_iterable(label): label = [label] * N while len(label) < len(ydata): label.append(label[0]) # concatenate if necessary if len(label) > legend_max: label[legend_max - 2] = '...' for n in range(legend_max - 1, len(label) - 1): label[n] = "_nolegend_" # clear the figure? if clear and not axes: _pylab.gcf().clear() # axes cleared later # setup axes if axes == "gca" or axes == None: axes = _pylab.gca() # if we're clearing the axes if clear: axes.clear() # set the current axes _pylab.axes(axes) # now loop over the list of data in xdata and ydata for n in range(0, len(xdata)): # get the label if label: l = str(label[n]) else: l = str(n) # calculate the x an y progressive shifts dx = xshift * (n / xshift_every) dy = yshift * (n / yshift_every) # if we're supposed to coarsen the data, do so. x = _fun.coarsen_array(xdata[n], coarsen) y = _fun.coarsen_array(ydata[n], coarsen) ey = _fun.coarsen_array(eydata[n], coarsen, 'quadrature') ex = _fun.coarsen_array(exdata[n], coarsen, 'quadrature') # update the style if not style == None: kwargs.update(style.next()) axes.errorbar(x + dx, y + dy, label=l, yerr=ey, xerr=ex, **kwargs) _pylab.xscale(xscale) _pylab.yscale(yscale) if legend: axes.legend(loc=legend) axes.set_xlabel(xlabel) axes.set_ylabel(ylabel) # for some arguments there should be no title. if title in [None, False, 0]: axes.set_title('') # add the commands to the title else: title = str(title) history = _fun.get_shell_history() for n in range(0, min(shell_history, len(history))): title = title + "\n" + history[n].split('\n')[0].strip() title = title + '\nPlot created ' + _time.asctime() axes.set_title(title) if grid: _pylab.grid(True) if autoformat: _pt.format_figure(draw=False) _pt.auto_zoom(axes=axes, draw=False) # update the canvas if draw: _pylab.ion() _pylab.draw() _pylab.show() return axes
def xy_data(xdata, ydata, eydata=None, exdata=None, label=None, xlabel='', ylabel='', \ title='', shell_history=1, xshift=0, yshift=0, xshift_every=1, yshift_every=1, \ coarsen=0, style=None, clear=True, axes=None, xscale='linear', yscale='linear', grid=False, \ legend='best', legend_max=20, autoformat=True, tall=False, draw=True, **kwargs): """ Plots specified data. xdata, ydata Arrays (or arrays of arrays) of data to plot eydata, exdata Arrays of x and y errorbar values label string or array of strings for the line labels xlabel='' label for the x-axis ylabel='' label for the y-axis title='' title for the axes; set to None to have nothing. shell_history=1 how many commands from the pyshell history to include with the title xshift=0, yshift=0 progressive shifts on the data, to make waterfall plots xshift_every=1 perform the progressive shift every 1 or n'th line. yshift_every=1 perform the progressive shift every 1 or n'th line. style style cycle object. clear=True if no axes are specified, clear the figure, otherwise clear just the axes. axes=None which axes to use, or "gca" for the current axes xscale,yscale 'linear' by default. Set either to 'log' for log axes grid=False Should we draw a grid on the axes? legend='best' where to place the legend (see pylab.legend()) Set this to None to ignore the legend. legend_max=20 number of legend entries before it's truncated with '...' autoformat=True Should we format the figure for printing? False Should the format be tall? draw=True whether or not to draw the plot after plotting **kwargs are sent to pylab.errorbar() """ _pylab.ioff() # make sure everything is at least iterable. if not _fun.is_iterable(xdata): xdata = [xdata] if not _fun.is_iterable(exdata): exdata = [exdata] if not _fun.is_iterable(ydata): ydata = [ydata] if not _fun.is_iterable(eydata): eydata = [eydata] # make sure at least xdata and ydata are 2-D if _fun.is_a_number(xdata[0]): xdata = [xdata] if _fun.is_a_number(ydata[0]): ydata = [ydata] # make sure the number of data sets agrees N = max(len(xdata),len(ydata)) for n in range(N-len( xdata)): xdata.append( xdata[0]) for n in range(N-len( ydata)): ydata.append( ydata[0]) for n in range(N-len(exdata)): exdata.append(exdata[0]) for n in range(N-len(eydata)): eydata.append(eydata[0]) # loop over each x and y data set, making sure None's are all converted # to counting arrays for n in range(N): # clean up the [None]'s if _fun.is_iterable(xdata[n]) and xdata[n][0] is None: xdata[n] = None if _fun.is_iterable(ydata[n]) and ydata[n][0] is None: ydata[n] = None if xdata[n] is None and ydata[n] is None: print "ERROR: "+str(n)+"'th data set is (None, None)." return if xdata[n] is None: xdata[n] = _n.arange(len(ydata[n])) if ydata[n] is None: ydata[n] = _n.arange(len(xdata[n])) # check that the labels is a list of strings of the same length if not _fun.is_iterable(label): label = [label]*N while len(label) < len(ydata): label.append(label[0]) # concatenate if necessary if len(label) > legend_max: label[legend_max-2] = '...' for n in range(legend_max-1,len(label)-1): label[n] = "_nolegend_" # clear the figure? if clear and not axes: _pylab.gcf().clear() # axes cleared later # setup axes if axes=="gca" or axes is None: axes = _pylab.gca() # if we're clearing the axes if clear: axes.clear() # set the current axes _pylab.axes(axes) # now loop over the list of data in xdata and ydata for n in range(0,len(xdata)): # get the label if label: l = str(label[n]) else: l = str(n) # calculate the x an y progressive shifts dx = xshift*(n/xshift_every) dy = yshift*(n/yshift_every) # if we're supposed to coarsen the data, do so. x = _fun.coarsen_array(xdata[n], coarsen) y = _fun.coarsen_array(ydata[n], coarsen) ey = _fun.coarsen_array(eydata[n], coarsen, 'quadrature') ex = _fun.coarsen_array(exdata[n], coarsen, 'quadrature') # update the style if not style is None: kwargs.update(style.next()) axes.errorbar(x+dx, y+dy, label=l, yerr=ey, xerr=ex, **kwargs) _pylab.xscale(xscale) _pylab.yscale(yscale) if legend: axes.legend(loc=legend) axes.set_xlabel(xlabel) axes.set_ylabel(ylabel) # for some arguments there should be no title. if title in [None, False, 0]: axes.set_title('') # add the commands to the title else: title = str(title) history = _fun.get_shell_history() for n in range(0, min(shell_history, len(history))): title = title + "\n" + history[n].split('\n')[0].strip() title = title + '\nPlot created ' + _time.asctime() axes.set_title(title) if grid: _pylab.grid(True) if autoformat: _pt.format_figure(draw=False) _pt.auto_zoom(axes=axes, draw=False) # update the canvas if draw: _pylab.ion() _pylab.draw() _pylab.show() return axes
def _match_data_sets(x,y): """ Makes sure everything is the same shape. "Intelligently". """ # If x is a value, use this for the step size. dx = 1.0 if _fun.is_a_number(x): dx = x x = None # Handle the None for x or y if x is None or len(x) == 0: # If x is None, y can be either [1,2] or [[1,2],[1,2]] or [] if len(y) == 0: x = [] elif _fun.is_iterable(y[0]): # make an array of arrays to match x = [] for n in range(len(y)): x.append(list(dx*_n.array(range(len(y[n]))))) else: x = list(range(len(y))) # If y is a value, use this for the step size. dy = 1.0 if _fun.is_a_number(y): dy = y y = None if y is None or len(y) == 0: # If y is none, x can be either [1,2] or [[1,2],[1,2]] or [] if len(x) == 0: y = [] elif _fun.is_iterable(x[0]): # make an array of arrays to match y = [] for n in range(len(x)): y.append(list(dy*_n.array(range(len(x[n]))))) else: y = list(range(len(x))) # At this point they should be matched, but may still be 1D # Default behavior: if all elements are numbers in both, assume they match if _fun.elements_are_numbers(x): x=[x] if _fun.elements_are_numbers(y): y=[y] # Make sure they are both lists (so append works!) if not type(x) == list: x = list(x) if not type(y) == list: y = list(y) # Make sure they're the same length while len(x) > len(y): y.append(y[-1]) while len(y) > len(x): x.append(x[-1]) # Second default behavior: shared array [1,2,3], [[1,2,1],[1,2,1]] or vis versa if _fun.elements_are_numbers(x) and not _fun.elements_are_numbers(y): x = [x]*len(y) if _fun.elements_are_numbers(y) and not _fun.elements_are_numbers(x): y = [y]*len(x) # Clean up any remaining Nones for n in range(len(x)): if x[n] is None: x[n] = list(range(len(y[n]))) if y[n] is None: y[n] = list(range(len(x[n]))) return x, y
def databoxes(ds, xscript=0, yscript=1, eyscript=None, exscript=None, g=None, plotter=xy_data, transpose=False, **kwargs): """ Plots the listed databox objects with the specified scripts. ds list of databoxes xscript script for x data yscript script for y data eyscript script for y error exscript script for x error plotter function used to do the plotting transpose applies databox.transpose() prior to plotting g optional dictionary of globals for the supplied scripts **kwargs are sent to plotter() """ if not _fun.is_iterable(ds): ds = [ds] if 'xlabel' not in kwargs: kwargs['xlabel'] = str(xscript) if 'ylabel' not in kwargs: kwargs['ylabel'] = str(yscript) # First make sure everything is a list of scripts (or None's) if not _fun.is_iterable(xscript): xscript = [xscript] if not _fun.is_iterable(yscript): yscript = [yscript] if not _fun.is_iterable(exscript): exscript = [exscript] if not _fun.is_iterable(eyscript): eyscript = [eyscript] # make sure exscript matches shape with xscript (and the same for y) if len(exscript) < len(xscript): for n in range(len(xscript) - 1): exscript.append(exscript[0]) if len(eyscript) < len(yscript): for n in range(len(yscript) - 1): eyscript.append(eyscript[0]) # Make xscript and exscript match in shape with yscript and eyscript if len(xscript) < len(yscript): for n in range(len(yscript) - 1): xscript.append(xscript[0]) exscript.append(exscript[0]) # check for the reverse possibility if len(yscript) < len(xscript): for n in range(len(xscript) - 1): yscript.append(yscript[0]) eyscript.append(eyscript[0]) # now check for None's (counting scripts) for n in range(len(xscript)): if xscript[n] is None and yscript[n] is None: print("Two None scripts? But... why?") return if xscript[n] is None: if type(yscript[n]) == str: xscript[n] = 'range(len(' + yscript[n] + '))' else: xscript[n] = 'range(len(c(' + str(yscript[n]) + ')))' if yscript[n] is None: if type(xscript[n]) == str: yscript[n] = 'range(len(' + xscript[n] + '))' else: yscript[n] = 'range(len(c(' + str(xscript[n]) + ')))' xdatas = [] ydatas = [] exdatas = [] eydatas = [] labels = [] # Loop over all the data boxes for i in range(len(ds)): # Reset the default globals all_globals = dict(n=i, m=len(ds) - 1 - i) # Update them with the user-specified globals if not g == None: all_globals.update(g) # For ease of coding d = ds[i] # Take the transpose if necessary if transpose: d = d.transpose() # Generate the x-data; returns a list of outputs, one for each xscript xdata = d(xscript, all_globals) # Loop over each xdata, appending to the master list, and generating a label for n in range(len(xdata)): xdatas.append(xdata[n]) # Normal data set is a 1d array labels.append(_os.path.split(d.path)[-1]) # Special case: single-point per file if _fun.is_a_number(xdata[0]) == 1 and len(ds) > 1: labels = [ _os.path.split(ds[0].path)[-1] + ' - ' + _os.path.split(ds[-1].path)[-1] ] # Append the other data sets to their master lists for y in d(yscript, all_globals): ydatas.append(y) for x in d(exscript, all_globals): exdatas.append(x) for y in d(eyscript, all_globals): eydatas.append(y) if "label" in kwargs: labels = kwargs.pop("label") plotter(xdatas, ydatas, eydatas, exdatas, label=labels, **kwargs)