Skip to content

Commit

Permalink
Add plot_traces method to MultiplePSD class (#621)
Browse files Browse the repository at this point in the history
* Add plot_traces method to MultiplePSD class

Fixes #614

Adds function `plot_traces` to the `Multiple_PSD` class, alongside unit tests.

---

For more details, open the [Copilot Workspace session](https://copilot-workspace.githubnext.com/LinkedEarth/Pyleoclim_util/issues/614?shareId=XXXX-XXXX-XXXX-XXXX).

* remove errant test file

* improvements to psds.plot_traces and tests

* made ensembleseries.plot_traces actually accept linestyle arg

* delete errant test notebook
  • Loading branch information
alexkjames authored Nov 7, 2024
1 parent 84baeaa commit af4d62c
Show file tree
Hide file tree
Showing 8 changed files with 213 additions and 3 deletions.
5 changes: 5 additions & 0 deletions .devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"tasks": {
"build": "pip install -e ."
}
}
2 changes: 2 additions & 0 deletions condaenv.6d4f03jk.requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pyhht
-e .
2 changes: 2 additions & 0 deletions condaenv.k07sdt7n.requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pyhht
-e .
2 changes: 2 additions & 0 deletions oryx-build-commands.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
PlatformWithVersion=Python
BuildCommands=conda env create --file environment.yml --prefix ./venv --quiet
2 changes: 1 addition & 1 deletion pyleoclim/core/ensembleseries.py
Original file line number Diff line number Diff line change
Expand Up @@ -812,7 +812,7 @@ def plot_traces(self, figsize=[10, 4], xlabel=None, ylabel=None, title=None, num

for idx in random_draw_idx:
self.series_list[idx].plot(xlabel=xlabel, ylabel=ylabel, zorder=99, linewidth=lw,
xlim=xlim, ylim=ylim, ax=ax, color=color, alpha=alpha,linestyle='-', label='_ignore')
xlim=xlim, ylim=ylim, ax=ax, color=color, alpha=alpha,linestyle=linestyle, label='_ignore')
l1, = ax.plot(np.nan, np.nan, color=color, label=f'example members (n={num_traces})',linestyle='-')

if title is not None:
Expand Down
178 changes: 178 additions & 0 deletions pyleoclim/core/psds.py
Original file line number Diff line number Diff line change
Expand Up @@ -1406,3 +1406,181 @@ def plot_envelope(self, figsize=[10, 4], qs=[0.025, 0.5, 0.975],
else:
return ax

def plot_traces(self, figsize=[10, 4], in_loglog=True, in_period=True, xlabel=None, ylabel='PSD', title=None, num_traces=10, seed=None,
xticks=None, yticks=None, xlim=None, ylim=None, linestyle='-', savefig_settings=None, ax=None, legend=True,
color=sns.xkcd_rgb['pale red'], lw=0.5, alpha=0.3, lgd_kwargs=None):
'''Plot MultiplePSD as a subset of traces.
Parameters
----------
figsize : list, optional
The figure size. The default is [10, 4].
in_loglog : bool, optional
Plot in log space. The default is True.
in_period : bool, optional
Whether to plot periodicity instead of frequency. The default is True.
xlabel : str, optional
x-axis label. The default is None.
ylabel : str, optional
y-axis label. The default is None.
title : str, optional
Plot title. The default is None.
xticks : list, optional
x-ticks label. The default is None.
yticks : list, optional
y-ticks label. The default is None.
xlim : list, optional
x-axis limits. The default is None.
ylim : list, optional
y-axis limits. The default is None.
color : str, optional
Color of the traces. The default is sns.xkcd_rgb['pale red'].
alpha : float, optional
Transparency of the lines representing the multiple members. The default is 0.3.
linestyle : {'-', '--', '-.', ':', '', (offset, on-off-seq), ...}
Set the linestyle of the line
lw : float, optional
Width of the lines representing the multiple members. The default is 0.5.
num_traces : int, optional
Number of traces to plot. The default is 10.
savefig_settings : dict, optional
the dictionary of arguments for plt.savefig(); some notes below:
- "path" must be specified; it can be any existed or non-existed path,
with or without a suffix; if the suffix is not given in "path", it will follow "format"
- "format" can be one of {"pdf", "eps", "png", "ps"} The default is None.
ax : matplotlib.ax, optional
Matplotlib axis on which to return the plot. The default is None.
legend : bool; {True,False}, optional
Whether to plot the legend. The default is True.
lgd_kwargs : dict, optional
Parameters for the legend. The default is None.
seed : int, optional
Set the seed for the random number generator. Useful for reproducibility. The default is None.
Returns
-------
fig : matplotlib.figure
the figure object from matplotlib
See [matplotlib.pyplot.figure](https://matplotlib.org/3.1.1/api/_as_gen/matplotlib.pyplot.figure.html) for details.
ax : matplotlib.axis
the axis object from matplotlib
See [matplotlib.axes](https://matplotlib.org/api/axes_api.html) for details.
See also
--------
pyleoclim.utils.plotting.savefig : Saving figure in Pyleoclim
Examples
--------
.. jupyter-execute::
nn = 30 # number of noise realizations
nt = 500 # timeseries length
psds = []
time, signal = pyleo.utils.gen_ts(model='colored_noise',nt=nt,alpha=1.0)
ts = pyleo.Series(time=time, value = signal, verbose=False).standardize()
noise = np.random.randn(nt,nn)
for idx in range(nn): # noise
ts = pyleo.Series(time=time, value=signal+10*noise[:,idx], verbose=False)
psd = ts.spectral()
psds.append(psd)
mPSD = pyleo.MultiplePSD(psds)
fig, ax = mPSD.plot_traces()
'''
savefig_settings = {} if savefig_settings is None else savefig_settings.copy()
lgd_kwargs = {} if lgd_kwargs is None else lgd_kwargs.copy()

num_traces = min(num_traces, len(self.psd_list)) # restrict to the smaller of the two

if num_traces < 2:
raise ValueError('Number of traces to plot must be at least 2')

# generate default axis labels
if xlabel is None:
xlabel = 'Frequency'

if ylabel is None:
ylabel = 'Amplitude'

if ax is None:
fig, ax = plt.subplots(figsize=figsize)

if num_traces > 0:
if seed is not None:
np.random.seed(seed)

npsd = np.size(self.psd_list)
random_draw_idx = np.random.choice(npsd, num_traces, replace=False)

for idx in random_draw_idx:
self.psd_list[idx].plot(in_loglog=in_loglog, in_period=in_period, xlabel=xlabel, ylabel=ylabel, zorder=99, linewidth=lw,
xlim=xlim, ylim=ylim, xticks=xticks, yticks=yticks, ax=ax, color=color, alpha=alpha,linestyle=linestyle, label='_ignore')
l1, = ax.plot(np.nan, np.nan, color=color, label=f'example members (n={num_traces})',linestyle='-')

if title is not None:
ax.set_title(title)

if legend==True:
lgd_args = {'frameon': False}
lgd_args.update(lgd_kwargs)
ax.legend(**lgd_args)
elif legend==False:
ax.legend().remove()
else:
raise ValueError('legend should be set to either True or False')

if 'fig' in locals():
if 'path' in savefig_settings:
plotting.savefig(fig, settings=savefig_settings)
return fig, ax
else:
return ax
2 changes: 1 addition & 1 deletion pyleoclim/tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ def ensembleseries_science():
soi = pyleo.utils.load_dataset('SOI')
ens = pyleo.EnsembleSeries([soi for _ in range(5)])
for series in ens.series_list:
series.value += np.random.randn(len(series))
series.value += np.random.randn(len(series.value))
return ens

@pytest.fixture
Expand Down
23 changes: 22 additions & 1 deletion pyleoclim/tests/test_core_MultiplePSD.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,4 +88,25 @@ def test_plot_envelope_t0(self):
ts_surrs = pyleo.MultipleSeries(series_list=series_list)
psds = ts_surrs.spectral(method='mtm')
fig, ax = psds.plot_envelope()
pyleo.closefig(fig)
pyleo.closefig(fig)

class TestUiMultiplePsdPlotTraces:
''' Tests for MultiplePSD.plot_traces()
'''

def test_plot_traces_t0(self,multipleseries_science):
''' Test MultiplePSD.plot_traces() of a list of colored noise
'''
ts_surrs = multipleseries_science
psds = ts_surrs.spectral()
fig, _ = psds.plot_traces()
pyleo.closefig(fig)

def test_plot_traces_t1(self,ensembleseries_science):
''' Test MultiplePSD.plot_traces() with different numbers of traces
'''

ts_surrs = ensembleseries_science
psds = ts_surrs.spectral()
fig, _ = psds.plot_traces(num_traces=5)
pyleo.closefig(fig)

0 comments on commit af4d62c

Please sign in to comment.