PlasmaCalcs.plotting.xarray_timelines.XarrayTimelines

class PlasmaCalcs.plotting.xarray_timelines.XarrayTimelines(array, t='t', dims=None, *, werr=False, cycles=None, short_cycle_ok=False, dmax=UNSET, styles=None, plot=True, label=None, add_legend=True, legend_cols_align=True, legend_max_rows=20, skipna=False, robust=UNSET, ymargin=None, ybounds=None, xincrease=None, **kw_super)

Bases: PlotSettingsMixin

plotting lines vs time for an xarray.
array: xarray.DataArray or xarray.Dataset
the array to plot.
Must have coord or dimension with name self.t (probably ‘t’ or ‘snap’).
if dataset, will be converted to DataArray with new dim named ‘variable’.
t: str
name for the time coordinate (to be plotted along the x axis).
if ‘snap’, use int(snap) for snap in array.coords[‘snap’].
if ‘snap_str’, use int(str(snap)) for snap in array.coords[‘snap’]
if looks like ‘{cname}_index’ or ‘log_{cname}’, and not in array yet,
but cname in array, array.pc.fill_coords() to infer the t coord to use.
if any other value, use array.coords[t].values.
if array.coords[t].dtype==object, convert to strs when plotting.
e.g. [Fluid(‘e’), Fluid(‘H+’)] –> ticks with ‘e’, ‘H+’.
dims: None or list-like of str/None objects.
the dimensions; plot one line for each combination of dimensions.
None –> infer, based on array and t.
list-like –> if any element is None, infer it based on the other dims.
werr: bool, ‘bar’, or ‘fill’
if array is a Dataset with ‘mean’ and ‘std’, use this to just plot mean, with error bars.
(else, werr=False is the only valid option.)
True –> equivalent to ‘bar’
‘bar’ –> plt.errorbar
‘fill’ –> plt.fill_between
Note: if using werr, can pass any kwargs here, (of plt.errorbar or plt.fill_between) for style.
E.g. capsize=5, elinewidth=3, capthick=5
cycles: None or list-like of dict/Cycler/None objects.
the styles to use for each dimension. Must have length >= len(dims).
E.g. cycles=[dict(color=[‘r’, ‘b’, ‘g’]), dict(linestyle=[‘-’, ‘–‘])]
–> dims[0] will cycle through colors; dims[1] will cycle through linestyles.
None –> use DEFAULTS.PLOT.TIMELINES_CYCLE0, and (if needed) DEFAULTS.PLOT.TIMELINES_CYCLE1.
(default: [None, {‘ls’: [‘-’, ‘–’, ‘:’, ‘-.’, (0, (3, 1, 1, 1, 1, 1))]}])
if len(dims) > 2, this will fail.
list-like –> if any element is None, use plt.rcParams[‘axes.prop_cycle’] for that dimension;
and cannot have more than 1 None cycle.
short_cycle_ok: bool
whether it is okay for cycles to be shorter than the number of points in that dimension.
dmax: UNSET, None, or int
maximum length of a timelines dimension before crashing (with TooManyPlottablesError).
This prevents accidentally asking to make plot with hundreds of lines or more,
e.g. if array has maindims in it due to forgetting to use ‘mean_’.
Not applied to self.t dimension, which can be any length,
since t goes along an axis instead of having 1 line for each.
UNSET –> self.dmax = DEFAULTS.PLOT.TIMELINES_DMAX (default: 10)
None –> no maximum. Use with caution.
int –> maximum length.
styles: None or list-like of dicts.
the styles to use for each line. i’th line will use styles[i].
if any value in styles dicts conflicts with cycles, use value from syles instead of cycle.
plot: bool
whether to call self.plot() immediately, during init.
label: None or str
if provided, prepend this value to all lines’ labels generated by this XarrayTimelines.
(If it doesn’t end with whitespace, add a single space. E.g. “myinfo” –> “myinfo “.)
Useful if plotting timelines on the same axes as other information.
add_legend: bool
whether to plot a legend, by default.
legend_cols_align: bool
whether to align legend cols such that one of the dims (the longest one), is the same in each row.
E.g. if True, and self.dims = [‘fluid’, ‘component’], with more fluids than components,
then ‘fluid’ will be the same across each row.
Only applied if len(self) > legend_max_rows > (number of rows when cols aligned)
legend_max_rows: None or int
maximum number of rows in the legend. Add legend columns if len(self) > legend_max_rows.
(For more precise control, make your own legend after plotting…)
None –> no maximum.
skipna: bool
whether to drop NaN values before plotting each line of values.
robust: UNSET, bool, or number between 0 and 50 (default: UNSET)
use np.percentile when determining vmin/vmax, if robust.
For imshow/image plots, this refers to colorbar lims; for line plots, this refers to y lims.
UNSET –> use DEFAULTS.PLOT.ROBUST (default: True).
False –> just use min and max of values, don’t use percentile.
True –> use DEFAULTS.PLOT.ROBUST_PERCENTILE (default: 2.0)
number –> use np.percentile with this percentile for vmin (and 100 - this percentile for vmax).
Will consider minimum vmin and maximum vmax across all lines, to avoid fully-hiding lines.
ymargin: None or number (greater than -0.5, probably close to 0.05) (default: None)
margin to use for x/y axis, as a fraction of the data interval for that axis.
None –> use matplotlib defaults
(e.g., plt.rcParams[“axes.xmargin”] or [“axes.ymargin”], or 0 if using imshow)
positive number –> pad around the data region, with this much whitespace.
E.g. 0.05 means adding 5% whitespace on each side.
Use this to zoom out.
negative number –> remove this much of the outer parts of the data region.
E.g. -0.2 means removing 20% space from each side.
Use this to zoom in.
For line plots, if also using robust, ymargin will be applied to the robust y lims.
(margin-related params share the same docstring, but refer to:
‘xmargin’: x-axis, ‘ymargin’: y-axis, ‘margin’: x and/or y-axis.)
ybounds: None, False, or 2-tuple/iterable of [max_ymin, min_ymax] (default: None)
tells the (maximum ymin, minimum ymax) when determining ylims.
None –> use the current ylims if current_axes_has_data(), else (None, None).
False –> equivalent to (None, None), i.e. ignore this setting.
E.g., overlaying multiple plots; plot 1 from -10 to 10, plot 2 from -5 to 15;
by default would use plot 2 ybounds=(-10, 10) –> final ylims of (-10, 15).
If provided plot 2 ybounds=(-7, 12), would instead have ylims of (-7, 15).
xincrease: None or bool
whether the x-axis should increase from left to right.
None –> False if monotonically nonincreasing. I.e., False if all(t[i+1] <= t[i]), else True.
(“if t values are obviously inverted, take it as a hint from user to do xincrease=False”)
Additional kwargs go to super().__init__, and eventually to a plotting routine. Options include:
- self.plot_settings.get_mpl_kwargs(‘plt.legend’)
- self.plot_settings.get_mpl_kwargs(‘plt.plot’)
- self.plot_settings.get_mpl_kwargs(‘plt.errorbar’) # if werr=True or ‘bar’
- self.plot_settings.get_mpl_kwargs(‘plt.fill_between’) # if werr=’fill’
(Note that any plot settings which also appear in cycles will use the cycles values,
e.g. if ‘linestyle’ appears in cycle but also in kwargs, use the cycle value instead.)
— Examples —
import PlasmaCalcs as pc
# basic usage:
array.pc.timelines() # make timelines plot with default settings.
# alternative call signature:
pc.XarrayTimelines(array) # same result as above ^
# specify cycle:
# for dims[0], use plt.rcParams[‘axes.prop_cycle’];
# for dims[1], use a gradient in alpha (instead of the default, which is different linestyles):
array.pc.timelines(cycles=[None, dict(alpha=np.linspace(1, 0.3, 10)])
# use linewidth and linestyle in cycle for dims[1], use colors for dims[0]:
array.pc.timelines(cycles=[None, dict(linewidth=[5, 4, 3, 2], linestyle=[‘-’, ‘–’, ‘:’, ‘-.’])])
# specify handlelength (for legend, ensure lines are long enough to see):
array.pc.timelines(handlelength=5)
__init__(array, t='t', dims=None, *, werr=False, cycles=None, short_cycle_ok=False, dmax=UNSET, styles=None, plot=True, label=None, add_legend=True, legend_cols_align=True, legend_max_rows=20, skipna=False, robust=UNSET, ymargin=None, ybounds=None, xincrease=None, **kw_super)

Methods

__init__(array[, t, dims, werr, cycles, ...])

add_labels()

get_effective_data_interval(*[, robust])

iter_dimpoints()

legend([ncols])

plot(*[, legend, add_labels, robust, ...])

set_ylim(*[, robust, ymargin, ybounds])

add_labels()
add labels to plot, based on self.array.
get_effective_data_interval(*, robust=UNSET)
returns (vmin, vmax) taken across all lines in self.
If robust, take min vmin(line) and max vmax(line) across all lines.
robust: {robust}
If UNSET, use self.plot_settings.get(‘robust’). (if still UNSET, use behavior described above.)
iter_dimpoints()
iterates through points across all dimensions.
Yields (dimsel, style) pairs, where:
dimsel = dict of {dim: (i of dim at this point)} for dim in self.dims
style = dict of {matplotlib kwarg: value} which are relevant at this point.
legend(ncols=None)
plot the legend for the current plot, via plt.legend().
legend anchored to upper right corner of plot, outside the axes.
if self.legend_max_rows is not None:
put a limit on nrows.
if self.legend_cols_align is True:
align the columns such that (the longest) one of the dims is the same in each row.
Only applied if len(self) > legend_max_rows > (number of rows when cols aligned)
ncols: None or int
number of columns to use in the legend.
None –> picks a decent-looking value, based on self.legend_max_rows.
For more precise legend control, use plt.legend() instead.
plot(*, legend=UNSET, add_labels=True, robust=UNSET, ymargin=None, ybounds=UNSET, **kw_plot)
plot the lines vs time. Probably via plt.plot.
(if self.werr, might instead use plt.errorbar or plt.fill_between.)
legend: UNSET or bool
whether to plt.legend().
UNSET –> use legend = self.add_legend (default: True)
note: if all labels are None or empty string, will never attempt to add legend.
add_labels: bool
whether to self.add_labels() to plot, based on self.array:
xlabel (self.t), and ylabel if known (self.array.name).
Also put units on those labels if self.array.attrs[‘units’] is provided.
robust: {robust}
If robust, take min vmin(line) and max vmax(line) across all lines.
If UNSET, use self.plot_settings.get(‘robust’). (if still UNSET, use behavior described above.)
ymargin: {ymargin}
If None, use self.plot_settings.get(‘ymargin’) instead.
ybounds: {ybounds}
if UNSET, use self.plot_settings.get(‘ybounds’) instead.
set_ylim(*, robust=UNSET, ymargin=None, ybounds=UNSET)
sets plt.ylim() to a nice range for viewing all lines from self.
robust: {robust}
If robust, take min vmin(line) and max vmax(line) across all lines.
If UNSET, use self.plot_settings.get(‘robust’). (if still UNSET, use behavior described above.)
ymargin: {ymargin}
If None, use self.plot_settings.get(‘ymargin’) instead.
ybounds: {ybounds}
if UNSET, use self.plot_settings.get(‘ybounds’) instead.