Source code for pytplot.options

# Copyright 2018 Regents of the University of Colorado. All Rights Reserved.
# Released under the MIT license.
# This software was developed at the University of Colorado's Laboratory for Atmospheric and Space Physics.
# Verify current version before use at: https://github.com/MAVENSDC/PyTplot

import pytplot
import numpy as np
from pytplot import tplot_utilities as utilities
from copy import deepcopy

[docs]def options(name, option=None, value=None, opt_dict=None): """ This function allows the user to set a large variety of options for individual plots. Parameters: name : str Name or number of the tplot variable option : str The name of the option. See section below. value : str/int/float/list The value of the option. See section below. dict : dict This can be a dictionary of option:value pairs. Option and value will not be needed if this dictionary item is supplied. Options: =================== ========== ===== Options Value type Notes =================== ========== ===== Color str/list red, green, blue, etc. Also takes in RGB tuples, i.e. (0,255,0) for green Colormap str/list https://matplotlib.org/examples/color/colormaps_reference.html. Spec int 1 sets the Tplot Variable to spectrogram mode, 0 reverts. Alt int 1 sets the Tplot Variable to altitude plot mode, 0 reverts. Map int 1 sets the Tplot Variable to latitude/longitude mode, 0 reverts. link list Allows a user to reference one tplot variable to another. ylog int 1 sets the y axis to log scale, 0 reverts. zlog int 1 sets the z axis to log scale, 0 reverts (spectrograms only). legend_names list A list of strings that will be used to identify the lines. xlog_slice bool Sets x axis on slice plot to log scale if True. ylog bool Set y axis on main plot window to log scale if True. ylog_slice bool Sets y axis on slice plot to log scale if True. zlog bool Sets z axis on main plot window to log scale if True. line_style str scatter (to make scatter plots), or solid_line, dot, dash, dash_dot, dash_dot_dot_dot, long_dash. char_size int Defines character size for plot labels, etc. name str The title of the plot. panel_size flt Number between (0,1], representing the percent size of the plot. basemap str Full path and name of a background image for "Map" plots. alpha flt Number between [0,1], gives the transparency of the plot lines. thick flt Sets plot line width. yrange flt list Two numbers that give the y axis range of the plot. zrange flt list Two numbers that give the z axis range of the plot. xrange_slice flt list Two numbers that give the x axis range of spectrogram slicing plots. yrange_slice flt list Two numbers that give the y axis range of spectrogram slicing plots. ytitle str Title shown on the y axis. Use backslash for new lines. ztitle str Title shown on the z axis. Spec plots only. Use backslash for new lines. ysubtitle str Subtitle shown on the y axis. zsubtitle str Subtitle shown on the z axis. Spec plots only. plotter str Allows a user to implement their own plotting script in place of the ones herein. crosshair_x str Title for x-axis crosshair. crosshair_y str Title for y-axis crosshair. crosshair_z str Title for z-axis crosshair. static str Datetime string that gives desired time to plot y and z values from a spec plot. static_tavg str Datetime string that gives desired time-averaged y and z values to plot from a spec plot. t_average int Seconds around which the cursor is averaged when hovering over spectrogram plots. spec_plot_dim int/str If variable has more than two dimensions, this sets which dimension the v variable will display on the y axis in spectrogram plots. All other dimensions are summed into this one, unless "spec_slices_to_use" is also set for this variable. spec_dim_to_plot int/str Same as spec_plot_dim, just with a slightly more descriptive name spec_slices_to_use str Must be a dictionary of coordinate:values. If a variable has more than two dimensions, spectrogram plots will plot values at that particular slice of that dimension. See examples for how it works. border bool Turns on or off the top/right axes that would create a box around the plot var_label_ticks int Sets the number of ticks if this variable is displayed as an alternative x axis =================== ========== ===== Returns: None Examples: >>> # Change the y range of Variable1 >>> import pytplot >>> x_data = [1,2,3,4,5] >>> y_data = [1,2,3,4,5] >>> pytplot.store_data("Variable1", data={'x':x_data, 'y':y_data}) >>> pytplot.options('Variable1', 'yrange', [2,4]) >>> # Change Variable1 to use a log scale >>> pytplot.options('Variable1', 'ylog', 1) >>> # Set the spectrogram plots to show dimension 'v2' at slice 'v1' = 0 >>> pytplot.options("Variable2", "spec_dim_to_plot", 'v2') >>> pytplot.options("Variable2", "spec_slices_to_use", {'v1': 0}) """ if isinstance(name, int): name = list(pytplot.data_quants.keys())[name] if opt_dict is None: opt_dict = {option: value} else: if not isinstance(opt_dict,dict): print("dict must be a dictionary object. Returning.") return if not isinstance(name, list): name = [name] for i in name: for option, value in opt_dict.items(): # Lower case option for consistency option = option.lower() if i not in pytplot.data_quants.keys(): print(str(i) + " is currently not in pytplot.") return if option == 'color': if isinstance(value, list): pytplot.data_quants[i].attrs['plot_options']['extras']['line_color'] = value else: pytplot.data_quants[i].attrs['plot_options']['extras']['line_color'] = [value] if option == 'link': if isinstance(value, list): pytplot.link(i, value[1], value[0]) if option == 'colormap': if isinstance(value, list): pytplot.data_quants[i].attrs['plot_options']['extras']['colormap'] = value else: pytplot.data_quants[i].attrs['plot_options']['extras']['colormap'] = [value] if option == 'spec': _reset_plots(i) if value: if 'spec_bins' not in pytplot.data_quants[i].coords: print(f"{i} does not contain coordinates for spectrogram plotting. Continuing...") continue else: pytplot.data_quants[i].attrs['plot_options']['extras']['spec'] = value pytplot.data_quants[i].attrs['plot_options']['yaxis_opt']['y_range'] = utilities.get_y_range(pytplot.data_quants[i]) else: pytplot.data_quants[i].attrs['plot_options']['extras']['spec'] = value pytplot.data_quants[i].attrs['plot_options']['yaxis_opt']['y_range'] = utilities.get_y_range(pytplot.data_quants[i]) # Set the default dimension to plot by. All others will be summed over. if 'spec_dim_to_plot' not in pytplot.data_quants[i].attrs['plot_options']['extras']: if 'v' in pytplot.data_quants[i].coords: pytplot.data_quants[i].attrs['plot_options']['extras']['spec_dim_to_plot'] = 'v' elif 'v2' in pytplot.data_quants[i].coords: pytplot.data_quants[i].attrs['plot_options']['extras']['spec_dim_to_plot'] = 'v2' else: pytplot.data_quants[i].attrs['plot_options']['extras']['spec_dim_to_plot'] = 'v1' if option == 'alt': _reset_plots(i) pytplot.data_quants[i].attrs['plot_options']['extras']['alt'] = value if option == 'map': _reset_plots(i) pytplot.data_quants[i].attrs['plot_options']['extras']['map'] = value if option == 'legend_names': if isinstance(value, list): pytplot.data_quants[i].attrs['plot_options']['yaxis_opt']['legend_names'] = value else: pytplot.data_quants[i].attrs['plot_options']['yaxis_opt']['legend_names'] = [value] if option == 'xlog_slice': if value: pytplot.data_quants[i].attrs['plot_options']['slice_xaxis_opt']['xi_axis_type'] = 'log' else: pytplot.data_quants[i].attrs['plot_options']['slice_xaxis_opt']['xi_axis_type'] = 'linear' if option == 'ylog': negflag = 0 # _ylog_check(data_quants, value, i) if negflag == 0 and value: pytplot.data_quants[i].attrs['plot_options']['yaxis_opt']['y_axis_type'] = 'log' else: pytplot.data_quants[i].attrs['plot_options']['yaxis_opt']['y_axis_type'] = 'linear' if option == 'ylog_slice': if value: pytplot.data_quants[i].attrs['plot_options']['slice_yaxis_opt']['yi_axis_type'] = 'log' else: pytplot.data_quants[i].attrs['plot_options']['slice_yaxis_opt']['yi_axis_type'] = 'linear' if option == 'zlog': # check for negative values and warn the user that they will be ignored negflag = _zlog_check(pytplot.data_quants, value, i) if negflag != 0 and value: print(str(i) + ' contains negative values; setting the z-axis to log scale will cause the negative values to be ignored on figures.') if value: pytplot.data_quants[i].attrs['plot_options']['zaxis_opt']['z_axis_type'] = 'log' else: pytplot.data_quants[i].attrs['plot_options']['zaxis_opt']['z_axis_type'] = 'linear' if option == 'nodata': pytplot.data_quants[i].attrs['plot_options']['line_opt']['visible'] = value if option == 'line_style': if value == 0 or value == 'solid_line': to_be = [] elif value == 1 or value == 'dot': to_be = [2, 4] elif value == 2 or value == 'dash': to_be = [6] elif value == 3 or value == 'dash_dot': to_be = [6, 4, 2, 4] elif value == 4 or value == 'dash_dot_dot_dot': to_be = [6, 4, 2, 4, 2, 4, 2, 4] elif value == 5 or value == 'long_dash': to_be = [10] else: to_be=value pytplot.data_quants[i].attrs['plot_options']['line_opt']['line_style'] = to_be if(value == 6 or value == 'none'): pytplot.data_quants[i].attrs['plot_options']['line_opt']['visible'] = False if option == 'char_size': pytplot.data_quants[i].attrs['plot_options']['extras']['char_size'] = value if option == 'name': pytplot.data_quants[i].attrs['plot_options']['line_opt']['name'] = value if option == "panel_size": if value > 1 or value <= 0: print("Invalid value. Should be (0, 1]") return pytplot.data_quants[i].attrs['plot_options']['extras']['panel_size'] = value if option == 'basemap': pytplot.data_quants[i].attrs['plot_options']['extras']['basemap'] = value if option == 'alpha': if value > 1 or value < 0: print("Invalid value. Should be [0, 1]") return pytplot.data_quants[i].attrs['plot_options']['extras']['alpha'] = value if option == 'thick': pytplot.data_quants[i].attrs['plot_options']['line_opt']['line_width'] = value if option == 'yrange' or option == 'y_range': pytplot.data_quants[i].attrs['plot_options']['yaxis_opt']['y_range'] = [value[0], value[1]] if option == 'zrange' or option == 'z_range': pytplot.data_quants[i].attrs['plot_options']['zaxis_opt']['z_range'] = [value[0], value[1]] if option == 'xrange_slice': pytplot.data_quants[i].attrs['plot_options']['slice_xaxis_opt']['xi_range'] = [value[0], value[1]] if option == 'yrange_slice': pytplot.data_quants[i].attrs['plot_options']['slice_yaxis_opt']['yi_range'] = [value[0], value[1]] if option == 'xtitle': pytplot.data_quants[i].attrs['plot_options']['xaxis_opt']['axis_label'] = value if option == 'ytitle': pytplot.data_quants[i].attrs['plot_options']['yaxis_opt']['axis_label'] = value if option == 'ztitle': pytplot.data_quants[i].attrs['plot_options']['zaxis_opt']['axis_label'] = value if option == 'xsubtitle': pytplot.data_quants[i].attrs['plot_options']['xaxis_opt']['axis_subtitle'] = value if option == 'ysubtitle': pytplot.data_quants[i].attrs['plot_options']['yaxis_opt']['axis_subtitle'] = value if option == 'zsubtitle': pytplot.data_quants[i].attrs['plot_options']['zaxis_opt']['axis_subtitle'] = value if option == 'ybar': pytplot.data_quants[i].attrs['plot_options']['extras']['ybar'] = value if option == 'ybar_color': pytplot.data_quants[i].attrs['plot_options']['extras']['ybar'] = value if option == 'ybar_size': pytplot.data_quants[i].attrs['plot_options']['extras']['ysize'] = value if option == 'plotter': _reset_plots(i) pytplot.data_quants[i].attrs['plot_options']['extras']['plotter'] = value if option == 'crosshair_x': pytplot.data_quants[i].attrs['plot_options']['xaxis_opt']['crosshair'] = value if option == 'crosshair_y': pytplot.data_quants[i].attrs['plot_options']['yaxis_opt']['crosshair'] = value if option == 'crosshair_z': pytplot.data_quants[i].attrs['plot_options']['zaxis_opt']['crosshair'] = value if option == 'static': pytplot.data_quants[i].attrs['plot_options']['extras']['static'] = value if option == 'static_tavg': pytplot.data_quants[i].attrs['plot_options']['extras']['static_tavg'] = [value[0], value[1]] if option == 't_average': pytplot.data_quants[i].attrs['plot_options']['extras']['t_average'] = value if option == 'spec_dim_to_plot' or option == 'spec_plot_dim': if len(pytplot.data_quants[i].values.shape) <= 2: print(f"Must have more than 2 coordinate dimensions to set spec_coord_to_plot for {pytplot.data_quants[i].name}") continue # Set the 'spec_dim_to_plot' value to either 'v' or 'v1', 'v2', 'v3', etc. if isinstance(value, int): coord_to_plot = "v" + str(value) if coord_to_plot not in pytplot.data_quants[i].coords: if value == 1: coord_to_plot = "v" if coord_to_plot not in pytplot.data_quants[i].coords: print(f"Dimension {value} not found in {pytplot.data_quants[i].name}") continue else: print(f"Dimension {value} not found in {pytplot.data_quants[i].name}") continue pytplot.data_quants[i].attrs['plot_options']['extras']['spec_dim_to_plot'] = coord_to_plot elif isinstance(value, str): coord_to_plot = value if coord_to_plot not in pytplot.data_quants[i].coords: print(f"Dimension {value} not found in {pytplot.data_quants[i].name}") continue else: pytplot.data_quants[i].attrs['plot_options']['extras']['spec_dim_to_plot'] = value # If we're plotting against different coordinates, we need to change what we consider the "spec_bins" pytplot.data_quants[i].coords['spec_bins'] = pytplot.data_quants[i].coords[coord_to_plot] pytplot.data_quants[i].attrs['plot_options']['yaxis_opt']['y_range'] = utilities.get_y_range(pytplot.data_quants[i]) if option == 'spec_slices_to_use': if not isinstance(value, dict): print("Must be a dictionary object in the format {'v2':15, 'v3':7}") return else: for coord in value: if coord not in pytplot.data_quants[i].coords: print(f"Dimension {coord} not found in {pytplot.data_quants[i].name}") continue pytplot.data_quants[i].attrs['plot_options']['extras']['spec_slices_to_use'] = value if option == 'border': pytplot.data_quants[i].attrs['plot_options']['extras']['border'] = value if option == 'var_label_ticks': pytplot.data_quants[i].attrs['plot_options']['var_label_ticks'] = value return
def _ylog_check(data_quants, value, i): negflag = 0 namedata = data_quants[i] # check variable data # if negative numbers, don't allow log setting datasets = [namedata] for oplot_name in namedata.attrs['plot_options']['overplots']: datasets.append(data_quants[oplot_name]) if value == 1: for dataset in datasets: if 'spec' not in dataset.attrs['plot_options']['extras']: if dataset.min(skipna=True) < 0: print('Negative data is incompatible with log plotting.') negflag = 1 break else: if dataset.attrs['plot_options']['extras']['spec'] == 1: if dataset.coords['spec_bins'].min(skipna=True) < 0: print('Negative data is incompatible with log plotting.') negflag = 1 break elif value != 1: # Using the 'negflag' as a way to not log something if the user doesn't want it to be logged negflag = 1 return negflag def _zlog_check(data_quants, value, i): negflag = 0 namedata = data_quants[i] # check variable data # if negative numbers, don't allow log setting datasets = [namedata] for oplot_name in namedata.attrs['plot_options']['overplots']: datasets.append(data_quants[oplot_name]) for dataset in datasets: if value == 1: if 'spec' in dataset.attrs['plot_options']['extras']: if dataset.attrs['plot_options']['extras']['spec'] == 1: if dataset.min(skipna=True) < 0: negflag = 1 break elif value != 1: # Using the 'negflag' as a way to not log something if the user doesn't want it to be logged negflag = 1 return negflag def _reset_plots(name): pytplot.data_quants[name].attrs['plot_options']['extras']['spec'] = 0 pytplot.data_quants[name].attrs['plot_options']['extras']['alt'] = 0 pytplot.data_quants[name].attrs['plot_options']['extras']['map'] = 0 pytplot.data_quants[name].attrs['plot_options']['extras']['plotter'] = None