From 4b407ad2f14c8ed44cd107bd2d6572451d704db8 Mon Sep 17 00:00:00 2001 From: Alexander James Date: Tue, 5 Mar 2024 12:20:26 -0800 Subject: [PATCH 01/29] create multipleresolution.py --- pyleoclim/core/multipleresolution.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 pyleoclim/core/multipleresolution.py diff --git a/pyleoclim/core/multipleresolution.py b/pyleoclim/core/multipleresolution.py new file mode 100644 index 00000000..e69de29b From ee76ee25f1953e1c0e890df1afa36ba04e0befe1 Mon Sep 17 00:00:00 2001 From: Alexander James Date: Tue, 5 Mar 2024 12:20:48 -0800 Subject: [PATCH 02/29] create multipleresolution class --- pyleoclim/core/multipleresolution.py | 31 ++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/pyleoclim/core/multipleresolution.py b/pyleoclim/core/multipleresolution.py index e69de29b..85637efa 100644 --- a/pyleoclim/core/multipleresolution.py +++ b/pyleoclim/core/multipleresolution.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +MultipleResolution objects are designed to contain, display, and analyze information on the resolution of multiple time axes from a MultipleSeries, EnsembleSeries, or SurrogateSeries object. +""" + +from ..utils import tsutils, plotting, tsmodel, tsbase + +import warnings + +import numpy as np +import seaborn as sns +import pandas as pd +import scipy.stats as st +import matplotlib.pyplot as plt + +from matplotlib import gridspec + +class MultipleResolution: + ''' Resolution object + + Resolution objects store time axis resolution information derived from MultipleSeries objects. + They are generated via the resolution method applied to a MultipleSeries object and contain methods relevant to the analysis of resolution information. + + See Also + -------- + + ''' + + def __init__(self,resolution_list): + self.resolution_list = resolution_list \ No newline at end of file From f4197dad5f986c4976b0e81d26d93911b46904ec Mon Sep 17 00:00:00 2001 From: Alexander James Date: Tue, 5 Mar 2024 12:21:01 -0800 Subject: [PATCH 03/29] add resolution and multipleresolution to init --- pyleoclim/core/__init__.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pyleoclim/core/__init__.py b/pyleoclim/core/__init__.py index 66a192ab..5c1eadf0 100644 --- a/pyleoclim/core/__init__.py +++ b/pyleoclim/core/__init__.py @@ -19,3 +19,5 @@ from .ssares import SsaRes from .lipd import Lipd from .lipdseries import LipdSeries +from .resolution import Resolution +from .multipleresolution import MultipleResolution From 55a34bb039af7812cd6d5cbb60978caead7afb9b Mon Sep 17 00:00:00 2001 From: Alexander James Date: Tue, 5 Mar 2024 12:27:07 -0800 Subject: [PATCH 04/29] improve resolution docstring --- pyleoclim/core/resolution.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/pyleoclim/core/resolution.py b/pyleoclim/core/resolution.py index 921364f5..956fb8bc 100644 --- a/pyleoclim/core/resolution.py +++ b/pyleoclim/core/resolution.py @@ -22,6 +22,25 @@ class Resolution: Resolution objects store time axis resolution information derived from Series objects. They are generated via the resolution method applied to a Series object and contain methods relevant to the analysis of resolution information. + Parameters + ---------- + + resolution : list or numpy.array + An array containing information on the time step between subsequent values in the original time series. + + time : list or numpy.array + An array containing the time axis from the original series. + This should be same length as resolution, so removing one value from the original axis is required. + + resolution_unit : str + Unit of resolution. This should be the same as the original time axis. + + label : str + Label for the resolution object. + + timeseries : pyleoclim.Series + Original pyleoclim timeseries object. + See Also -------- From 6d6f6ade3dc9a060cb85c17558df5ca87d8fbc5b Mon Sep 17 00:00:00 2001 From: Alexander James Date: Tue, 5 Mar 2024 12:27:40 -0800 Subject: [PATCH 05/29] improve series.resolution clarity --- pyleoclim/core/series.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pyleoclim/core/series.py b/pyleoclim/core/series.py index c5ff32a4..1291ae15 100644 --- a/pyleoclim/core/series.py +++ b/pyleoclim/core/series.py @@ -4125,6 +4125,9 @@ def resolution(self): resolution = Resolution( resolution = res, + time = self.time, + resolution_unit=self.time_unit, + label=self.label, timeseries = copy ) From a9f9a4871a328d1a88bc38ba72cbb96d71c73cf2 Mon Sep 17 00:00:00 2001 From: Alexander James Date: Tue, 5 Mar 2024 12:39:39 -0800 Subject: [PATCH 06/29] minor docstring fix --- pyleoclim/core/series.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pyleoclim/core/series.py b/pyleoclim/core/series.py index 1291ae15..a99e1d85 100644 --- a/pyleoclim/core/series.py +++ b/pyleoclim/core/series.py @@ -4073,6 +4073,11 @@ def resolution(self): resolution : Resolution Resolution object + See Also + -------- + + pyleoclim.core.resolution.Resolution + Examples -------- From 98ed19e3d86d6aa978c3c57bc743d5ee2f240174 Mon Sep 17 00:00:00 2001 From: Alexander James Date: Tue, 5 Mar 2024 12:41:02 -0800 Subject: [PATCH 07/29] create resolution function in multipleseries --- pyleoclim/core/multipleseries.py | 70 +++++++++++++++++++++++++++++++- 1 file changed, 69 insertions(+), 1 deletion(-) diff --git a/pyleoclim/core/multipleseries.py b/pyleoclim/core/multipleseries.py index 204bbd3e..b75877b1 100644 --- a/pyleoclim/core/multipleseries.py +++ b/pyleoclim/core/multipleseries.py @@ -11,6 +11,7 @@ from ..core.scalograms import MultipleScalogram from ..core.psds import MultiplePSD from ..core.multivardecomp import MultivariateDecomp +from ..core.multipleresolution import MultipleResolution import warnings import numpy as np @@ -2654,4 +2655,71 @@ def time_coverage_plot(self, figsize=[10, 3], plotting.savefig(fig, settings=savefig_settings) return fig, ax else: - return ax \ No newline at end of file + return ax + + def resolution(self): + """Generate a MultipleResolution object + + Increments are assigned to the preceding time value. + E.g. for time_axis = [0,1,3], resolution.resolution = [1,2] resolution.time = [0,1] + + Returns + ------- + + multipleresolution : pyleoclim.MultipleResolution + MultipleResolution object + + See Also + -------- + + pyleoclim.core.multipleresolution.MultipleResolution + + Examples + -------- + + To create a resolution object, apply the .resolution() method to a Series object + + .. jupyter-execute:: + + import pyleoclim as pyleo + + co2ts = pyleo.utils.load_dataset('AACO2') + lr04 = pyleo.utils.load_dataset('LR04') + edc = pyleo.utils.load_dataset('EDC-dD') + ms = lr04.flip() & edc & co2ts # create MS object + ms_resolution = ms.resolution() + + Several methods are then available: + + Summary statistics can be obtained via .describe() + + .. jupyter-execute:: + + resolution.describe() + + A simple plot can be created using .plot() + + .. jupyter-execute:: + + resolution.plot() + + The distribution of resolution + + .. jupyter-execute:: + + resolution.histplot() + + Or a dashboard combining plot() and histplot() side by side: + + .. jupyter-execute:: + + resolution.dashboard() + """ + + resolution_list = [] + + for series in self.series_list: + resolution = series.resolution() + resolution_list.append(resolution) + + return MultipleResolution(resolution_list=resolution_list) \ No newline at end of file From 006fd160dd9b3561ae52d2e4d5bdd2fbd5e2138b Mon Sep 17 00:00:00 2001 From: Alexander James Date: Tue, 5 Mar 2024 14:28:21 -0800 Subject: [PATCH 08/29] docstring change --- pyleoclim/core/multipleseries.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pyleoclim/core/multipleseries.py b/pyleoclim/core/multipleseries.py index b75877b1..bc63f5d7 100644 --- a/pyleoclim/core/multipleseries.py +++ b/pyleoclim/core/multipleseries.py @@ -2695,25 +2695,25 @@ def resolution(self): .. jupyter-execute:: - resolution.describe() + ms_resolution.describe() A simple plot can be created using .plot() .. jupyter-execute:: - resolution.plot() + ms_resolution.plot() The distribution of resolution .. jupyter-execute:: - resolution.histplot() + ms_resolution.histplot() Or a dashboard combining plot() and histplot() side by side: .. jupyter-execute:: - resolution.dashboard() + ms_resolution.dashboard() """ resolution_list = [] From 326494934640c08813d5f2874f74de9bb765b49d Mon Sep 17 00:00:00 2001 From: Alexander James Date: Tue, 5 Mar 2024 15:16:36 -0800 Subject: [PATCH 09/29] include time unit in multipleresolution --- pyleoclim/core/multipleresolution.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pyleoclim/core/multipleresolution.py b/pyleoclim/core/multipleresolution.py index 85637efa..a77f6dd6 100644 --- a/pyleoclim/core/multipleresolution.py +++ b/pyleoclim/core/multipleresolution.py @@ -27,5 +27,6 @@ class MultipleResolution: ''' - def __init__(self,resolution_list): - self.resolution_list = resolution_list \ No newline at end of file + def __init__(self,resolution_list,time_unit): + self.resolution_list = resolution_list + self.time_unit = time_unit \ No newline at end of file From 3d9feb387d165d99fa6dfbf7b766e5f2009a0b1c Mon Sep 17 00:00:00 2001 From: Alexander James Date: Tue, 5 Mar 2024 15:16:47 -0800 Subject: [PATCH 10/29] multipleseries.resolution improvement --- pyleoclim/core/multipleseries.py | 42 ++++++++++++++++++++++++++------ 1 file changed, 35 insertions(+), 7 deletions(-) diff --git a/pyleoclim/core/multipleseries.py b/pyleoclim/core/multipleseries.py index bc63f5d7..de0519ee 100644 --- a/pyleoclim/core/multipleseries.py +++ b/pyleoclim/core/multipleseries.py @@ -2657,11 +2657,12 @@ def time_coverage_plot(self, figsize=[10, 3], else: return ax - def resolution(self): + def resolution(self,time_unit=None,verbose=True): """Generate a MultipleResolution object Increments are assigned to the preceding time value. - E.g. for time_axis = [0,1,3], resolution.resolution = [1,2] resolution.time = [0,1] + E.g. for time_axis = [0,1,3], resolution.resolution = [1,2] resolution.time = [0,1]. + Note that the MultipleResolution class requires a shared time unit. If the time_unit parameter is not passed, a time unit will be automatically determined. Returns ------- @@ -2669,11 +2670,19 @@ def resolution(self): multipleresolution : pyleoclim.MultipleResolution MultipleResolution object + time_unit : str + Time unit to convert objects to. See pyleo.Series.convert_time_unit for options. + + verbose : bool + Whether or not to print messages warning the user about automated decisions. + See Also -------- pyleoclim.core.multipleresolution.MultipleResolution + pyleoclim.core.series.Series.convert_time_unit + Examples -------- @@ -2718,8 +2727,27 @@ def resolution(self): resolution_list = [] - for series in self.series_list: - resolution = series.resolution() - resolution_list.append(resolution) - - return MultipleResolution(resolution_list=resolution_list) \ No newline at end of file + if time_unit: + series_list = self.series_list + for series in series_list: + resolution = series.convert_time_unit(time_unit).resolution() + resolution_list.append(resolution) + else: + if self.time_unit: + series_list = self.series_list + for series in series_list: + resolution = series.resolution() + resolution_list.append(resolution) + else: + if verbose: + print('Time unit not found, attempting conversion.') + new_ms = self.convert_time_unit() + time_unit = new_ms.time_unit + series_list = new_ms.series_list + if verbose: + print(f'Converted to {time_unit}') + for series in series_list: + resolution = series.resolution() + resolution_list.append(resolution) + + return MultipleResolution(resolution_list=resolution_list,time_unit=time_unit) \ No newline at end of file From 64756cf2e689eb2bfb7028384f3f5317eb19f598 Mon Sep 17 00:00:00 2001 From: Alexander James Date: Tue, 5 Mar 2024 15:16:54 -0800 Subject: [PATCH 11/29] multipleseries.resolution tests --- pyleoclim/tests/test_core_MultipleSeries.py | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/pyleoclim/tests/test_core_MultipleSeries.py b/pyleoclim/tests/test_core_MultipleSeries.py index d4af154b..dea7fb38 100644 --- a/pyleoclim/tests/test_core_MultipleSeries.py +++ b/pyleoclim/tests/test_core_MultipleSeries.py @@ -689,8 +689,25 @@ def test_invalid(self): class TestUIMultipleSeriesTimeCoveragePlot: def test_time_coverage_plot_t0(self,multipleseries_basic): ''' - test PCA output + test coverage plot ''' ms = multipleseries_basic fig,ax = ms.time_coverage_plot() - pyleo.closefig(fig) \ No newline at end of file + pyleo.closefig(fig) + +class TestUIMultipleSeriesResolution: + def test_time_coverage_plot_t0(self,multipleseries_basic): + ''' + test resolution class + ''' + ms = multipleseries_basic + ms.resolution() + def test_time_coverage_plot_t1(self): + ''' + test resolution class with time unit + ''' + co2ts = pyleo.utils.load_dataset('AACO2') + lr04 = pyleo.utils.load_dataset('LR04') + edc = pyleo.utils.load_dataset('EDC-dD') + ms = lr04.flip() & edc & co2ts # create MS object + ms.resolution(time_unit='kyr BP') \ No newline at end of file From 78060b95397720a8c310211ca964418bb65ebe11 Mon Sep 17 00:00:00 2001 From: Alexander James Date: Tue, 5 Mar 2024 16:24:28 -0800 Subject: [PATCH 12/29] bug fixes --- pyleoclim/core/multipleresolution.py | 11 +++++- pyleoclim/core/multipleseries.py | 57 ++++++++++++++-------------- pyleoclim/core/resolution.py | 10 ++--- pyleoclim/core/series.py | 9 ++--- 4 files changed, 45 insertions(+), 42 deletions(-) diff --git a/pyleoclim/core/multipleresolution.py b/pyleoclim/core/multipleresolution.py index a77f6dd6..b97e44f6 100644 --- a/pyleoclim/core/multipleresolution.py +++ b/pyleoclim/core/multipleresolution.py @@ -29,4 +29,13 @@ class MultipleResolution: def __init__(self,resolution_list,time_unit): self.resolution_list = resolution_list - self.time_unit = time_unit \ No newline at end of file + self.time_unit = time_unit + + def plot(self,ax=None,figsize=(10,8)): + """Boxplot showing distribution of resolutions from each resolution object""" + + if ax is None: + fig,ax = plt.subplots(figsize=figsize) + + df = pd.DataFrame(columns=['Resolution','Label']) + \ No newline at end of file diff --git a/pyleoclim/core/multipleseries.py b/pyleoclim/core/multipleseries.py index de0519ee..83da5b4f 100644 --- a/pyleoclim/core/multipleseries.py +++ b/pyleoclim/core/multipleseries.py @@ -2324,42 +2324,41 @@ def sel(self, value=None, time=None, tolerance=0): return ms_new - def resolution(self, statistic='median'): - ''' - Extracts representative statistic for the resolution of each series in the object. - - Parameters - ---------- - statistic : str, optional - The statistic applied to the res9lution array of each series. - Possible values: 'mean' or 'median'. The default is 'median'. + # def resolution(self, statistic='median'): + # ''' + # Extracts representative statistic for the resolution of each series in the object. + # Parameters + # ---------- + # statistic : str, optional + # The statistic applied to the res9lution array of each series. + # Possible values: 'mean' or 'median'. The default is 'median'. - Returns - ------- - res: NumPy array - array containing the statistic of interest for all series. + # Returns + # ------- + # res: NumPy array + # array containing the statistic of interest for all series. - Examples - -------- - .. jupyter-execute:: + # Examples + # -------- + # .. jupyter-execute:: - co2ts = pyleo.utils.load_dataset('AACO2') - edc = pyleo.utils.load_dataset('EDC-dD') - ms = edc & co2ts # create MS object - ms.convert_time_unit('kyr BP').resolution() + # co2ts = pyleo.utils.load_dataset('AACO2') + # edc = pyleo.utils.load_dataset('EDC-dD') + # ms = edc & co2ts # create MS object + # ms.convert_time_unit('kyr BP').resolution() - Note that the output is only meaningful if all constituent series have the same units. - ''' + # Note that the output is only meaningful if all constituent series have the same units. + # ''' - if statistic=='median': - res = [np.median(ts.resolution().resolution) for ts in self.series_list] - elif statistic=='mean': - res = [np.mean(ts.resolution().resolution) for ts in self.series_list] - else: - raise ValueError('Unknown statistic',stacklevel=2) + # if statistic=='median': + # res = [np.median(ts.resolution().resolution) for ts in self.series_list] + # elif statistic=='mean': + # res = [np.mean(ts.resolution().resolution) for ts in self.series_list] + # else: + # raise ValueError('Unknown statistic',stacklevel=2) - return np.array(res) + # return np.array(res) def to_json(self, path=None): ''' diff --git a/pyleoclim/core/resolution.py b/pyleoclim/core/resolution.py index 956fb8bc..1c59bf61 100644 --- a/pyleoclim/core/resolution.py +++ b/pyleoclim/core/resolution.py @@ -48,7 +48,6 @@ class Resolution: def __init__(self,resolution,time=None,resolution_unit=None,label=None,timeseries=None,): resolution = np.array(resolution) - self.resolution = resolution self.timeseries = timeseries @@ -57,6 +56,8 @@ def __init__(self,resolution,time=None,resolution_unit=None,label=None,timeserie self.label = 'Resolution' else: self.label = self.timeseries.label + else: + self.label = label if time is None: self.time = self.timeseries.time[1:] @@ -69,12 +70,9 @@ def __init__(self,resolution,time=None,resolution_unit=None,label=None,timeserie self.resolution_unit = timeseries.time_unit else: self.resolution_unit = resolution_unit - #Include time reasoning - elif resolution_unit is not None: - if timeseries is not None: - if timeseries.time_unit.lower().replace(' ','') != resolution_unit.lower().replace(' ',''): - warnings.warn('Original series time unit and passed resolution unit do not match') + else: + self.resolution_unit = resolution_unit def describe(self): diff --git a/pyleoclim/core/series.py b/pyleoclim/core/series.py index a99e1d85..03e6d138 100644 --- a/pyleoclim/core/series.py +++ b/pyleoclim/core/series.py @@ -4130,17 +4130,14 @@ def resolution(self): resolution = Resolution( resolution = res, - time = self.time, - resolution_unit=self.time_unit, - label=self.label, + time = self.time[1:], + resolution_unit= self.time_unit, + label= self.label, timeseries = copy ) return resolution - - - class SeriesResampler: """ This is only meant to be used internally, and is not meant to From f366d373b3228cc4f5388ca7d18c91267418a187 Mon Sep 17 00:00:00 2001 From: Alexander James Date: Wed, 6 Mar 2024 10:57:37 -0800 Subject: [PATCH 13/29] multipleresolution plot and describe functions --- pyleoclim/core/multipleresolution.py | 168 ++++++++++++++++++++++++++- 1 file changed, 164 insertions(+), 4 deletions(-) diff --git a/pyleoclim/core/multipleresolution.py b/pyleoclim/core/multipleresolution.py index b97e44f6..3cc420c5 100644 --- a/pyleoclim/core/multipleresolution.py +++ b/pyleoclim/core/multipleresolution.py @@ -31,11 +31,171 @@ def __init__(self,resolution_list,time_unit): self.resolution_list = resolution_list self.time_unit = time_unit - def plot(self,ax=None,figsize=(10,8)): - """Boxplot showing distribution of resolutions from each resolution object""" + def plot(self,figsize=(10,8),xlabel=None,ylabel=None,legend=False,ax=None, + boxplot_whis=[0,100], boxplot_width=.6, boxplot_dodge=False,boxplot_palette='viridis', + stripplot_size=2,stripplot_color=".3",stripplot_alpha=.8,stripplot_dodge=False, + boxplot_kwargs=None,stripplot_kwargs=None,savefig_settings=None): + """Boxplot showing distribution of resolutions from each resolution object + + Parameters + ---------- + + figsize : tuple, list + Size of the figure. + + xlabel : str + Label for the x axis. "Resolution [{time_unit}]" will be used by default. + + ylabel : str + Label for the y axis. Left empty by default. + + legend : bool + Whether or not to plot the legend. Default is False. + + ax : matplotlib.ax + The matplotlib axis onto which to return the figure. The default is None. + + boxplot_whis : float or pair of floats + If scalar, whiskers are drawn to the farthest datapoint within whis * IQR from the nearest hinge. + If a tuple, it is interpreted as percentiles that whiskers represent. Default is [0,100] + + boxplot_width : float + Width allotted to each element on the orient axis. + + boxplot_dodge : bool + Whether boxplot elements should be narrowed and shifted along the orient axis to eliminate overlap. Default is False. + + boxplot_palette : palette name, list, or dict + Colors to use for the different levels of the hue variable. + Should be something that can be interpreted by color_palette(), or a dictionary mapping hue levels to matplotlib colors. + Gets passed to seaborn.boxplot for details. + + stripplot_size : float + Size of stripplot markers. + + stripplot_color : str + Color for the stripplot markers. + + stripplot_alpha : float + Alpha for the stripplot markers. + + stripplot_dodge : bool + Whether stripplot elements should be narrowed and shifted along the orient axis to eliminate overlap. Default is False. + + boxplot_kwargs : dict + Dictionary of arguments for seaborn.boxplot. Arguments that are passed here will overwrite explicit arguments (e.g. whis, width, etc.). + + stripplot_kwargs : dict + Dictionary of argument for seaborn.stripplot. Arguments that are passed here will overwrite explicit arguments (e.g. size, color, etc.). + + savefig_settings : dictionary, optional + + the dictionary of arguments for pyleo.utils.plotting.savefig(); some notes below: + - "path" must be specified; it can be any existing or non-existing 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. + + Examples + -------- + .. jupyter-execute:: + import pyleoclim as pyleo + + co2ts = pyleo.utils.load_dataset('AACO2') + edc = pyleo.utils.load_dataset('EDC-dD') + ms = edc & co2ts # create MS object + ms_resolution = ms.resolution() + ms_resolution.plot() + """ + + boxplot_kwargs = {} if boxplot_kwargs is None else boxplot_kwargs.copy() + stripplot_kwargs = {} if stripplot_kwargs is None else stripplot_kwargs.copy() + savefig_settings = {} if savefig_settings is None else savefig_settings.copy() if ax is None: fig,ax = plt.subplots(figsize=figsize) - df = pd.DataFrame(columns=['Resolution','Label']) - \ No newline at end of file + data = pd.DataFrame(columns=['Resolution','Label']) + + for resolution in self.resolution_list: + for value in resolution.resolution: + data.loc[len(data),['Resolution','Label']] = [value,resolution.label] + + if 'whis' in boxplot_kwargs: + boxplot_whis = boxplot_kwargs.pop('whis') + if 'width' in boxplot_kwargs: + boxplot_width = boxplot_kwargs.pop('width') + if 'dodge' in boxplot_kwargs: + boxplot_dodge = boxplot_kwargs.pop('dodge') + if 'palette' in boxplot_kwargs: + boxplot_palette = boxplot_kwargs.pop('palette') + + if 'size' in stripplot_kwargs: + stripplot_size = stripplot_kwargs.pop('size') + if 'color' in stripplot_kwargs: + stripplot_color = stripplot_kwargs.pop('color') + if 'alpha' in stripplot_kwargs: + stripplot_alpha = stripplot_kwargs.pop('alpha') + if 'dodge' in stripplot_kwargs: + stripplot_dodge = stripplot_kwargs.pop('dodge') + + sns.boxplot(data,x='Resolution',y='Label',hue='Label',whis=boxplot_whis, width=boxplot_width, dodge=boxplot_dodge, palette=boxplot_palette, ax=ax, **boxplot_kwargs) + sns.stripplot(data, x="Resolution", y="Label",size=stripplot_size,color=stripplot_color,alpha=stripplot_alpha,dodge=stripplot_dodge,ax=ax,**stripplot_kwargs) + + if ylabel: + ax.set(ylabel=ylabel) + else: + ax.set(ylabel="") + + if xlabel: + ax.set(xlabel=xlabel) + else: + ax.set(xlabel=f"Resolution [{self.time_unit}]") + + if not legend: + ax.legend().set_visible(False) + + # Tweak the visual presentation + ax.xaxis.grid(True) + sns.despine(trim=True, left=True) + + if 'fig' in locals(): + if 'path' in savefig_settings: + plotting.savefig(fig, settings=savefig_settings) + return fig, ax + else: + return ax + + def describe(self): + '''Describe the stats of the resolution list + + Returns + ------- + + resolution_dict : dict + Dictionary of relevant stats produced by `scipy.stats.describe `_ + + Examples + -------- + + ..jupyter-execute:: + import pyleoclim as pyleo + + co2ts = pyleo.utils.load_dataset('AACO2') + edc = pyleo.utils.load_dataset('EDC-dD') + ms = edc & co2ts # create MS object + ms_resolution = ms.resolution() + ms_resolution.plot() + + ''' + + resolution_dict = {} + + for resolution in self.resolution_list: + stats = st.describe(resolution.resolution)._asdict() + + median = np.median(resolution.resolution) + stats['median'] = median + + resolution_dict[resolution.label] = stats + + return resolution_dict \ No newline at end of file From 07a34ba008a14a7ef677c1e6a4473d5df09fd89e Mon Sep 17 00:00:00 2001 From: Alexander James Date: Wed, 6 Mar 2024 11:20:03 -0800 Subject: [PATCH 14/29] docstring fixes --- pyleoclim/core/multipleseries.py | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/pyleoclim/core/multipleseries.py b/pyleoclim/core/multipleseries.py index 83da5b4f..c2c0008e 100644 --- a/pyleoclim/core/multipleseries.py +++ b/pyleoclim/core/multipleseries.py @@ -2692,9 +2692,8 @@ def resolution(self,time_unit=None,verbose=True): import pyleoclim as pyleo co2ts = pyleo.utils.load_dataset('AACO2') - lr04 = pyleo.utils.load_dataset('LR04') edc = pyleo.utils.load_dataset('EDC-dD') - ms = lr04.flip() & edc & co2ts # create MS object + ms = edc & co2ts # create MS object ms_resolution = ms.resolution() Several methods are then available: @@ -2710,18 +2709,6 @@ def resolution(self,time_unit=None,verbose=True): .. jupyter-execute:: ms_resolution.plot() - - The distribution of resolution - - .. jupyter-execute:: - - ms_resolution.histplot() - - Or a dashboard combining plot() and histplot() side by side: - - .. jupyter-execute:: - - ms_resolution.dashboard() """ resolution_list = [] From 26920ab7cd9caae463bb7fa45bc025fea1b1682a Mon Sep 17 00:00:00 2001 From: Alexander James Date: Wed, 6 Mar 2024 12:42:55 -0800 Subject: [PATCH 15/29] bugfix --- pyleoclim/core/series.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyleoclim/core/series.py b/pyleoclim/core/series.py index 03e6d138..ba1fb656 100644 --- a/pyleoclim/core/series.py +++ b/pyleoclim/core/series.py @@ -4130,7 +4130,7 @@ def resolution(self): resolution = Resolution( resolution = res, - time = self.time[1:], + time = x[1:], resolution_unit= self.time_unit, label= self.label, timeseries = copy From f7cedea745b41c3f4bd8aa1b9afb71ec119e94ed Mon Sep 17 00:00:00 2001 From: Alexander James Date: Wed, 6 Mar 2024 14:05:52 -0800 Subject: [PATCH 16/29] include default behaviour and tests + new conftest --- pyleoclim/core/multipleseries.py | 56 +++++++++++++-------- pyleoclim/tests/conftest.py | 13 +++++ pyleoclim/tests/test_core_MultipleSeries.py | 16 ++++-- 3 files changed, 59 insertions(+), 26 deletions(-) diff --git a/pyleoclim/core/multipleseries.py b/pyleoclim/core/multipleseries.py index c2c0008e..b3e81763 100644 --- a/pyleoclim/core/multipleseries.py +++ b/pyleoclim/core/multipleseries.py @@ -2331,7 +2331,7 @@ def sel(self, value=None, time=None, tolerance=0): # Parameters # ---------- # statistic : str, optional - # The statistic applied to the res9lution array of each series. + # The statistic applied to the resolution array of each series. # Possible values: 'mean' or 'median'. The default is 'median'. # Returns @@ -2656,7 +2656,7 @@ def time_coverage_plot(self, figsize=[10, 3], else: return ax - def resolution(self,time_unit=None,verbose=True): + def resolution(self,time_unit=None,verbose=True,statistic='median'): """Generate a MultipleResolution object Increments are assigned to the preceding time value. @@ -2675,6 +2675,10 @@ def resolution(self,time_unit=None,verbose=True): verbose : bool Whether or not to print messages warning the user about automated decisions. + statistic : str; {'median','mean',None} + If a recognized statistic is passed, this function will simply output that statistic applied to the resolution of each series in the MulitipleSeries object. Options are 'mean' or 'median'. + If statistic is None, then the function will return a new MultipleResolution class with plotting capabilities. + See Also -------- @@ -2711,29 +2715,37 @@ def resolution(self,time_unit=None,verbose=True): ms_resolution.plot() """ - resolution_list = [] + if statistic=='median': + res = [np.median(ts.resolution().resolution) for ts in self.series_list] + elif statistic=='mean': + res = [np.mean(ts.resolution().resolution) for ts in self.series_list] + elif statistic is None: + resolution_list = [] - if time_unit: - series_list = self.series_list - for series in series_list: - resolution = series.convert_time_unit(time_unit).resolution() - resolution_list.append(resolution) - else: - if self.time_unit: + if time_unit: series_list = self.series_list for series in series_list: - resolution = series.resolution() + resolution = series.convert_time_unit(time_unit).resolution() resolution_list.append(resolution) else: - if verbose: - print('Time unit not found, attempting conversion.') - new_ms = self.convert_time_unit() - time_unit = new_ms.time_unit - series_list = new_ms.series_list - if verbose: - print(f'Converted to {time_unit}') - for series in series_list: - resolution = series.resolution() - resolution_list.append(resolution) + if self.time_unit: + series_list = self.series_list + for series in series_list: + resolution = series.resolution() + resolution_list.append(resolution) + else: + if verbose: + print('Time unit not found, attempting conversion.') + new_ms = self.convert_time_unit() + time_unit = new_ms.time_unit + series_list = new_ms.series_list + if verbose: + print(f'Converted to {time_unit}') + for series in series_list: + resolution = series.resolution() + resolution_list.append(resolution) + res = MultipleResolution(resolution_list=resolution_list,time_unit=time_unit) + else: + raise ValueError('Unrecognized statistic, please use "mean", "median", or None') - return MultipleResolution(resolution_list=resolution_list,time_unit=time_unit) \ No newline at end of file + return res \ No newline at end of file diff --git a/pyleoclim/tests/conftest.py b/pyleoclim/tests/conftest.py index 66327dd0..579d1e2c 100644 --- a/pyleoclim/tests/conftest.py +++ b/pyleoclim/tests/conftest.py @@ -108,6 +108,19 @@ def multipleseries_basic(): ms = pyleo.MultipleSeries([ts1, ts2]) return ms +@pytest.fixture +def multipleseries_nans(): + t1 = np.arange(1,10) + v1 = np.ones(len(t1)) + ts1 = pyleo.Series(time=t1, value=v1) + + t2 = np.arange(1,10) + v2 = np.ones(len(t1)) + v2[2:4] = np.nan + ts2 = pyleo.Series(time=t2, value =v2, dropna=False, verbose=False) + ms = ts1 & ts2 + return ms + @pytest.fixture def multipleseries_science(): soi = pyleo.utils.load_dataset('SOI') diff --git a/pyleoclim/tests/test_core_MultipleSeries.py b/pyleoclim/tests/test_core_MultipleSeries.py index dea7fb38..d8b09e01 100644 --- a/pyleoclim/tests/test_core_MultipleSeries.py +++ b/pyleoclim/tests/test_core_MultipleSeries.py @@ -696,13 +696,21 @@ def test_time_coverage_plot_t0(self,multipleseries_basic): pyleo.closefig(fig) class TestUIMultipleSeriesResolution: - def test_time_coverage_plot_t0(self,multipleseries_basic): + @pytest.mark.parameterize('statistic',['mean',None]) + def test_time_coverage_plot_t0(self,statistic,multipleseries_basic): ''' test resolution class ''' ms = multipleseries_basic - ms.resolution() - def test_time_coverage_plot_t1(self): + ms.resolution(statistic=statistic) + @pytest.mark.parameterize('statistic',['mean',None]) + def test_time_coverage_plot_t1(self,statistic,multipleseries_nans): + ''' + test resolution class with nans + ''' + ms = multipleseries_nans # create MS object + ms.resolution(statistic=statistic) + def test_time_coverage_plot_t2(self): ''' test resolution class with time unit ''' @@ -710,4 +718,4 @@ def test_time_coverage_plot_t1(self): lr04 = pyleo.utils.load_dataset('LR04') edc = pyleo.utils.load_dataset('EDC-dD') ms = lr04.flip() & edc & co2ts # create MS object - ms.resolution(time_unit='kyr BP') \ No newline at end of file + ms.resolution(statistic=None,time_unit='kyr BP') \ No newline at end of file From 51453708dbb7e00f666148bf11334ccc2b4cf087 Mon Sep 17 00:00:00 2001 From: Alexander James Date: Wed, 6 Mar 2024 14:27:56 -0800 Subject: [PATCH 17/29] rename plot to summary plot --- pyleoclim/core/multipleresolution.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyleoclim/core/multipleresolution.py b/pyleoclim/core/multipleresolution.py index 3cc420c5..4e490c45 100644 --- a/pyleoclim/core/multipleresolution.py +++ b/pyleoclim/core/multipleresolution.py @@ -31,11 +31,11 @@ def __init__(self,resolution_list,time_unit): self.resolution_list = resolution_list self.time_unit = time_unit - def plot(self,figsize=(10,8),xlabel=None,ylabel=None,legend=False,ax=None, + def summary_plot(self,figsize=(10,8),xlabel=None,ylabel=None,legend=False,ax=None, boxplot_whis=[0,100], boxplot_width=.6, boxplot_dodge=False,boxplot_palette='viridis', stripplot_size=2,stripplot_color=".3",stripplot_alpha=.8,stripplot_dodge=False, boxplot_kwargs=None,stripplot_kwargs=None,savefig_settings=None): - """Boxplot showing distribution of resolutions from each resolution object + """Summary plot showing distribution of resolutions from each resolution object as box plots with overlaid strip plots. Parameters ---------- From 201ee47133583b6bd43c49a504a8fe520e98f017 Mon Sep 17 00:00:00 2001 From: Alexander James Date: Wed, 6 Mar 2024 14:28:04 -0800 Subject: [PATCH 18/29] deprecation warnings for statistic arg --- pyleoclim/core/multipleseries.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pyleoclim/core/multipleseries.py b/pyleoclim/core/multipleseries.py index b3e81763..929b8820 100644 --- a/pyleoclim/core/multipleseries.py +++ b/pyleoclim/core/multipleseries.py @@ -2714,10 +2714,12 @@ def resolution(self,time_unit=None,verbose=True,statistic='median'): ms_resolution.plot() """ - + if statistic=='median': + warnings.warn('The statistic parameter will be deprecated in a future release. Statistic = None will become the default behavior.',DeprecationWarning) res = [np.median(ts.resolution().resolution) for ts in self.series_list] elif statistic=='mean': + warnings.warn('The statistic parameter will be deprecated in a future release. Statistic = None will become the default behavior.',DeprecationWarning) res = [np.mean(ts.resolution().resolution) for ts in self.series_list] elif statistic is None: resolution_list = [] From cdf6322a46a7c00c1dd4f83dd7f17c67f8905c34 Mon Sep 17 00:00:00 2001 From: Alexander James Date: Wed, 6 Mar 2024 14:28:09 -0800 Subject: [PATCH 19/29] msr tests --- .../tests/test_core_MultipleResolution.py | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 pyleoclim/tests/test_core_MultipleResolution.py diff --git a/pyleoclim/tests/test_core_MultipleResolution.py b/pyleoclim/tests/test_core_MultipleResolution.py new file mode 100644 index 00000000..b6da90b5 --- /dev/null +++ b/pyleoclim/tests/test_core_MultipleResolution.py @@ -0,0 +1,74 @@ +''' Tests for pyleoclim.core.ui.MultipleResolution + +Naming rules: +1. class: Test{filename}{Class}{method} with appropriate camel case +2. function: test_{method}_t{test_id} + +Notes on how to test: +0. Make sure [pytest](https://docs.pytest.org) has been installed: `pip install pytest` +1. execute `pytest {directory_path}` in terminal to perform all tests in all testing files inside the specified directory +2. execute `pytest {file_path}` in terminal to perform all tests in the specified file +3. execute `pytest {file_path}::{TestClass}::{test_method}` in terminal to perform a specific test class/method inside the specified file +4. after `pip install pytest-xdist`, one may execute "pytest -n 4" to test in parallel with number of workers specified by `-n` +5. for more details, see https://docs.pytest.org/en/stable/usage.html +''' + +import pytest +import pyleoclim as pyleo + +class TestUIMultipleResolutionSummaryPlot: + def test_plot_t0(self,multipleseries_basic): + ''' + test resolution plot + ''' + ms = multipleseries_basic + msr = ms.resolution() + fig,ax=msr.summary_plot() + pyleo.closefig(fig) + def test_plot_t1(self,multipleseries_nans): + ''' + test resolution plot with nans + ''' + ms = multipleseries_nans # create MS object + ms.resolution() + msr = ms.resolutoin() + fig,ax=msr.summary_plot() + pyleo.closefig(fig) + def test_plot_t2(self): + ''' + test resolution plot with time unit + ''' + co2ts = pyleo.utils.load_dataset('AACO2') + lr04 = pyleo.utils.load_dataset('LR04') + edc = pyleo.utils.load_dataset('EDC-dD') + ms = lr04.flip() & edc & co2ts # create MS object + msr = ms.resolution(time_unit='kyr BP') + fig,ax=msr.summary_plot() + pyleo.closefig(fig) + +class TestUIMultipleResolutionDescribe: + def test_describe_t0(self,multipleseries_basic): + ''' + test resolution describe + ''' + ms = multipleseries_basic + msr = ms.resolution() + msr.describe() + def test_describe_t1(self,multipleseries_nans): + ''' + test resolution describe with nans + ''' + ms = multipleseries_nans # create MS object + ms.resolution() + msr = ms.resolutoin() + msr.describe() + def test_describe_t2(self): + ''' + test resolution plot with time unit + ''' + co2ts = pyleo.utils.load_dataset('AACO2') + lr04 = pyleo.utils.load_dataset('LR04') + edc = pyleo.utils.load_dataset('EDC-dD') + ms = lr04.flip() & edc & co2ts # create MS object + msr = ms.resolution(time_unit='kyr BP') + msr.describe() \ No newline at end of file From e72f38e14b4cc87e786f571e75f548270215e055 Mon Sep 17 00:00:00 2001 From: Alexander James Date: Wed, 6 Mar 2024 14:28:14 -0800 Subject: [PATCH 20/29] test fixes --- pyleoclim/tests/test_core_MultipleSeries.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pyleoclim/tests/test_core_MultipleSeries.py b/pyleoclim/tests/test_core_MultipleSeries.py index d8b09e01..81af7534 100644 --- a/pyleoclim/tests/test_core_MultipleSeries.py +++ b/pyleoclim/tests/test_core_MultipleSeries.py @@ -697,20 +697,20 @@ def test_time_coverage_plot_t0(self,multipleseries_basic): class TestUIMultipleSeriesResolution: @pytest.mark.parameterize('statistic',['mean',None]) - def test_time_coverage_plot_t0(self,statistic,multipleseries_basic): + def test_resolution(self,statistic,multipleseries_basic): ''' test resolution class ''' ms = multipleseries_basic ms.resolution(statistic=statistic) @pytest.mark.parameterize('statistic',['mean',None]) - def test_time_coverage_plot_t1(self,statistic,multipleseries_nans): + def test_resolution(self,statistic,multipleseries_nans): ''' test resolution class with nans ''' ms = multipleseries_nans # create MS object ms.resolution(statistic=statistic) - def test_time_coverage_plot_t2(self): + def test_resolution_t2(self): ''' test resolution class with time unit ''' From 4c4d908d9d7a4845550ed7f395a54a9b88ddf4e3 Mon Sep 17 00:00:00 2001 From: Alexander James Date: Wed, 6 Mar 2024 14:37:39 -0800 Subject: [PATCH 21/29] improve unit tests --- .../tests/test_core_MultipleResolution.py | 29 +++++-------------- pyleoclim/tests/test_core_MultipleSeries.py | 15 +++------- 2 files changed, 11 insertions(+), 33 deletions(-) diff --git a/pyleoclim/tests/test_core_MultipleResolution.py b/pyleoclim/tests/test_core_MultipleResolution.py index b6da90b5..aea92524 100644 --- a/pyleoclim/tests/test_core_MultipleResolution.py +++ b/pyleoclim/tests/test_core_MultipleResolution.py @@ -17,24 +17,16 @@ import pyleoclim as pyleo class TestUIMultipleResolutionSummaryPlot: - def test_plot_t0(self,multipleseries_basic): + @pytest.mark.parametrize('ms_fixture', ['multipleseries_basic','multipleseries_nans']) + def test_plot_t0(self,ms_fixture,request): ''' test resolution plot ''' - ms = multipleseries_basic + ms = request.getfixturevalue(ms_fixture) msr = ms.resolution() fig,ax=msr.summary_plot() pyleo.closefig(fig) - def test_plot_t1(self,multipleseries_nans): - ''' - test resolution plot with nans - ''' - ms = multipleseries_nans # create MS object - ms.resolution() - msr = ms.resolutoin() - fig,ax=msr.summary_plot() - pyleo.closefig(fig) - def test_plot_t2(self): + def test_plot_t1(self): ''' test resolution plot with time unit ''' @@ -47,21 +39,14 @@ def test_plot_t2(self): pyleo.closefig(fig) class TestUIMultipleResolutionDescribe: - def test_describe_t0(self,multipleseries_basic): + @pytest.mark.parametrize('ms_fixture', ['multipleseries_basic','multipleseries_nans']) + def test_describe_t0(self,ms_fixture,request): ''' test resolution describe ''' - ms = multipleseries_basic + ms = request.get(ms_fixture) msr = ms.resolution() msr.describe() - def test_describe_t1(self,multipleseries_nans): - ''' - test resolution describe with nans - ''' - ms = multipleseries_nans # create MS object - ms.resolution() - msr = ms.resolutoin() - msr.describe() def test_describe_t2(self): ''' test resolution plot with time unit diff --git a/pyleoclim/tests/test_core_MultipleSeries.py b/pyleoclim/tests/test_core_MultipleSeries.py index 81af7534..0e2c9788 100644 --- a/pyleoclim/tests/test_core_MultipleSeries.py +++ b/pyleoclim/tests/test_core_MultipleSeries.py @@ -696,21 +696,14 @@ def test_time_coverage_plot_t0(self,multipleseries_basic): pyleo.closefig(fig) class TestUIMultipleSeriesResolution: - @pytest.mark.parameterize('statistic',['mean',None]) - def test_resolution(self,statistic,multipleseries_basic): + @pytest.mark.parametrize(('statistic','ms_fixture'),(['mean',None],['multipleseries_basic','multipleseries_nans'])) + def test_resolution(self,statistic,ms_fixture,request): ''' test resolution class ''' - ms = multipleseries_basic - ms.resolution(statistic=statistic) - @pytest.mark.parameterize('statistic',['mean',None]) - def test_resolution(self,statistic,multipleseries_nans): - ''' - test resolution class with nans - ''' - ms = multipleseries_nans # create MS object + ms = request.get(ms_fixture) ms.resolution(statistic=statistic) - def test_resolution_t2(self): + def test_resolution_t1(self): ''' test resolution class with time unit ''' From f6de3b6b089a80cd2a434d592b42427f42b16786 Mon Sep 17 00:00:00 2001 From: Alexander James Date: Wed, 6 Mar 2024 14:38:35 -0800 Subject: [PATCH 22/29] unit test fix --- pyleoclim/tests/test_core_MultipleResolution.py | 2 +- pyleoclim/tests/test_core_MultipleSeries.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyleoclim/tests/test_core_MultipleResolution.py b/pyleoclim/tests/test_core_MultipleResolution.py index aea92524..a954c51d 100644 --- a/pyleoclim/tests/test_core_MultipleResolution.py +++ b/pyleoclim/tests/test_core_MultipleResolution.py @@ -44,7 +44,7 @@ def test_describe_t0(self,ms_fixture,request): ''' test resolution describe ''' - ms = request.get(ms_fixture) + ms = request.getfixturevalue(ms_fixture) msr = ms.resolution() msr.describe() def test_describe_t2(self): diff --git a/pyleoclim/tests/test_core_MultipleSeries.py b/pyleoclim/tests/test_core_MultipleSeries.py index 0e2c9788..89c20061 100644 --- a/pyleoclim/tests/test_core_MultipleSeries.py +++ b/pyleoclim/tests/test_core_MultipleSeries.py @@ -701,7 +701,7 @@ def test_resolution(self,statistic,ms_fixture,request): ''' test resolution class ''' - ms = request.get(ms_fixture) + ms = request.getfixturevalue(ms_fixture) ms.resolution(statistic=statistic) def test_resolution_t1(self): ''' From fa93376a44879e5755f48e7353143a5d06dafc2f Mon Sep 17 00:00:00 2001 From: Alexander James Date: Wed, 6 Mar 2024 14:57:54 -0800 Subject: [PATCH 23/29] bugfix --- pyleoclim/core/multipleseries.py | 3 ++- pyleoclim/tests/test_core_MultipleSeries.py | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/pyleoclim/core/multipleseries.py b/pyleoclim/core/multipleseries.py index 929b8820..e1677cb7 100644 --- a/pyleoclim/core/multipleseries.py +++ b/pyleoclim/core/multipleseries.py @@ -2746,7 +2746,8 @@ def resolution(self,time_unit=None,verbose=True,statistic='median'): for series in series_list: resolution = series.resolution() resolution_list.append(resolution) - res = MultipleResolution(resolution_list=resolution_list,time_unit=time_unit) + + res = MultipleResolution(resolution_list=resolution_list,time_unit=time_unit) else: raise ValueError('Unrecognized statistic, please use "mean", "median", or None') diff --git a/pyleoclim/tests/test_core_MultipleSeries.py b/pyleoclim/tests/test_core_MultipleSeries.py index 89c20061..339e2150 100644 --- a/pyleoclim/tests/test_core_MultipleSeries.py +++ b/pyleoclim/tests/test_core_MultipleSeries.py @@ -697,7 +697,7 @@ def test_time_coverage_plot_t0(self,multipleseries_basic): class TestUIMultipleSeriesResolution: @pytest.mark.parametrize(('statistic','ms_fixture'),(['mean',None],['multipleseries_basic','multipleseries_nans'])) - def test_resolution(self,statistic,ms_fixture,request): + def test_resolution_t0(self,statistic,ms_fixture,request): ''' test resolution class ''' From 33927366db5f476b52d431a8ae6f2767511418cd Mon Sep 17 00:00:00 2001 From: Alexander James Date: Wed, 6 Mar 2024 15:13:56 -0800 Subject: [PATCH 24/29] more test fixes --- pyleoclim/tests/test_core_MultipleResolution.py | 12 +++++++----- pyleoclim/tests/test_core_MultipleSeries.py | 4 +++- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/pyleoclim/tests/test_core_MultipleResolution.py b/pyleoclim/tests/test_core_MultipleResolution.py index a954c51d..1c3f84b6 100644 --- a/pyleoclim/tests/test_core_MultipleResolution.py +++ b/pyleoclim/tests/test_core_MultipleResolution.py @@ -23,7 +23,7 @@ def test_plot_t0(self,ms_fixture,request): test resolution plot ''' ms = request.getfixturevalue(ms_fixture) - msr = ms.resolution() + msr = ms.resolution(statistic=None) fig,ax=msr.summary_plot() pyleo.closefig(fig) def test_plot_t1(self): @@ -34,18 +34,20 @@ def test_plot_t1(self): lr04 = pyleo.utils.load_dataset('LR04') edc = pyleo.utils.load_dataset('EDC-dD') ms = lr04.flip() & edc & co2ts # create MS object - msr = ms.resolution(time_unit='kyr BP') + msr = ms.resolution(time_unit='kyr BP',statistic=None) fig,ax=msr.summary_plot() pyleo.closefig(fig) class TestUIMultipleResolutionDescribe: - @pytest.mark.parametrize('ms_fixture', ['multipleseries_basic','multipleseries_nans']) + @pytest.mark.parametrize( + ('statistic','ms_fixture'), + (['mean','multipleseries_basic'],[None,'multipleseries_basic'],['mean','multipleseries_nans'],[None,'multipleseries_nans'])) def test_describe_t0(self,ms_fixture,request): ''' test resolution describe ''' ms = request.getfixturevalue(ms_fixture) - msr = ms.resolution() + msr = ms.resolution(statistic=None) msr.describe() def test_describe_t2(self): ''' @@ -55,5 +57,5 @@ def test_describe_t2(self): lr04 = pyleo.utils.load_dataset('LR04') edc = pyleo.utils.load_dataset('EDC-dD') ms = lr04.flip() & edc & co2ts # create MS object - msr = ms.resolution(time_unit='kyr BP') + msr = ms.resolution(time_unit='kyr BP',statistic=None) msr.describe() \ No newline at end of file diff --git a/pyleoclim/tests/test_core_MultipleSeries.py b/pyleoclim/tests/test_core_MultipleSeries.py index 339e2150..6725ff7c 100644 --- a/pyleoclim/tests/test_core_MultipleSeries.py +++ b/pyleoclim/tests/test_core_MultipleSeries.py @@ -696,7 +696,9 @@ def test_time_coverage_plot_t0(self,multipleseries_basic): pyleo.closefig(fig) class TestUIMultipleSeriesResolution: - @pytest.mark.parametrize(('statistic','ms_fixture'),(['mean',None],['multipleseries_basic','multipleseries_nans'])) + @pytest.mark.parametrize( + ('statistic','ms_fixture'), + (['mean','multipleseries_basic'],[None,'multipleseries_basic'],['mean','multipleseries_nans'],[None,'multipleseries_nans'])) def test_resolution_t0(self,statistic,ms_fixture,request): ''' test resolution class From c72d8532c53a475263ec572a634fa433426e001c Mon Sep 17 00:00:00 2001 From: Alexander James Date: Wed, 6 Mar 2024 15:17:26 -0800 Subject: [PATCH 25/29] last unit test fix (maybe) --- pyleoclim/tests/test_core_MultipleResolution.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/pyleoclim/tests/test_core_MultipleResolution.py b/pyleoclim/tests/test_core_MultipleResolution.py index 1c3f84b6..c2069dfa 100644 --- a/pyleoclim/tests/test_core_MultipleResolution.py +++ b/pyleoclim/tests/test_core_MultipleResolution.py @@ -39,9 +39,7 @@ def test_plot_t1(self): pyleo.closefig(fig) class TestUIMultipleResolutionDescribe: - @pytest.mark.parametrize( - ('statistic','ms_fixture'), - (['mean','multipleseries_basic'],[None,'multipleseries_basic'],['mean','multipleseries_nans'],[None,'multipleseries_nans'])) + @pytest.mark.parametrize('ms_fixture', ['multipleseries_basic','multipleseries_nans']) def test_describe_t0(self,ms_fixture,request): ''' test resolution describe From b3c8379d0ee9051412e583df6023d429896453ba Mon Sep 17 00:00:00 2001 From: Alexander James Date: Thu, 7 Mar 2024 10:09:41 -0800 Subject: [PATCH 26/29] increase seaborn version requirement --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index a0eb6d37..4bec2cc3 100644 --- a/setup.py +++ b/setup.py @@ -31,7 +31,7 @@ def read(fname): "pandas==2.1.4", "kneed>=0.7.0", "statsmodels>=0.13.2", - "seaborn==0.12.2", + "seaborn>=0.13.0", "scikit-learn>=0.24.2", "pathos>=0.2.8", "tqdm>=4.61.2", From ceb7fc56d1cbbf2f91b87cda0528c42cd3fad653 Mon Sep 17 00:00:00 2001 From: Alexander James Date: Thu, 7 Mar 2024 10:10:06 -0800 Subject: [PATCH 27/29] various fixes --- pyleoclim/core/__init__.py | 3 +- pyleoclim/core/multipleresolution.py | 201 ------------------ pyleoclim/core/multipleseries.py | 50 +---- .../core/{resolution.py => resolutions.py} | 195 ++++++++++++++++- pyleoclim/core/series.py | 4 +- 5 files changed, 204 insertions(+), 249 deletions(-) delete mode 100644 pyleoclim/core/multipleresolution.py rename pyleoclim/core/{resolution.py => resolutions.py} (63%) diff --git a/pyleoclim/core/__init__.py b/pyleoclim/core/__init__.py index 5c1eadf0..d08e971e 100644 --- a/pyleoclim/core/__init__.py +++ b/pyleoclim/core/__init__.py @@ -19,5 +19,4 @@ from .ssares import SsaRes from .lipd import Lipd from .lipdseries import LipdSeries -from .resolution import Resolution -from .multipleresolution import MultipleResolution +from .resolutions import Resolution, MultipleResolution diff --git a/pyleoclim/core/multipleresolution.py b/pyleoclim/core/multipleresolution.py deleted file mode 100644 index 4e490c45..00000000 --- a/pyleoclim/core/multipleresolution.py +++ /dev/null @@ -1,201 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -""" -MultipleResolution objects are designed to contain, display, and analyze information on the resolution of multiple time axes from a MultipleSeries, EnsembleSeries, or SurrogateSeries object. -""" - -from ..utils import tsutils, plotting, tsmodel, tsbase - -import warnings - -import numpy as np -import seaborn as sns -import pandas as pd -import scipy.stats as st -import matplotlib.pyplot as plt - -from matplotlib import gridspec - -class MultipleResolution: - ''' Resolution object - - Resolution objects store time axis resolution information derived from MultipleSeries objects. - They are generated via the resolution method applied to a MultipleSeries object and contain methods relevant to the analysis of resolution information. - - See Also - -------- - - ''' - - def __init__(self,resolution_list,time_unit): - self.resolution_list = resolution_list - self.time_unit = time_unit - - def summary_plot(self,figsize=(10,8),xlabel=None,ylabel=None,legend=False,ax=None, - boxplot_whis=[0,100], boxplot_width=.6, boxplot_dodge=False,boxplot_palette='viridis', - stripplot_size=2,stripplot_color=".3",stripplot_alpha=.8,stripplot_dodge=False, - boxplot_kwargs=None,stripplot_kwargs=None,savefig_settings=None): - """Summary plot showing distribution of resolutions from each resolution object as box plots with overlaid strip plots. - - Parameters - ---------- - - figsize : tuple, list - Size of the figure. - - xlabel : str - Label for the x axis. "Resolution [{time_unit}]" will be used by default. - - ylabel : str - Label for the y axis. Left empty by default. - - legend : bool - Whether or not to plot the legend. Default is False. - - ax : matplotlib.ax - The matplotlib axis onto which to return the figure. The default is None. - - boxplot_whis : float or pair of floats - If scalar, whiskers are drawn to the farthest datapoint within whis * IQR from the nearest hinge. - If a tuple, it is interpreted as percentiles that whiskers represent. Default is [0,100] - - boxplot_width : float - Width allotted to each element on the orient axis. - - boxplot_dodge : bool - Whether boxplot elements should be narrowed and shifted along the orient axis to eliminate overlap. Default is False. - - boxplot_palette : palette name, list, or dict - Colors to use for the different levels of the hue variable. - Should be something that can be interpreted by color_palette(), or a dictionary mapping hue levels to matplotlib colors. - Gets passed to seaborn.boxplot for details. - - stripplot_size : float - Size of stripplot markers. - - stripplot_color : str - Color for the stripplot markers. - - stripplot_alpha : float - Alpha for the stripplot markers. - - stripplot_dodge : bool - Whether stripplot elements should be narrowed and shifted along the orient axis to eliminate overlap. Default is False. - - boxplot_kwargs : dict - Dictionary of arguments for seaborn.boxplot. Arguments that are passed here will overwrite explicit arguments (e.g. whis, width, etc.). - - stripplot_kwargs : dict - Dictionary of argument for seaborn.stripplot. Arguments that are passed here will overwrite explicit arguments (e.g. size, color, etc.). - - savefig_settings : dictionary, optional - - the dictionary of arguments for pyleo.utils.plotting.savefig(); some notes below: - - "path" must be specified; it can be any existing or non-existing 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. - - Examples - -------- - .. jupyter-execute:: - import pyleoclim as pyleo - - co2ts = pyleo.utils.load_dataset('AACO2') - edc = pyleo.utils.load_dataset('EDC-dD') - ms = edc & co2ts # create MS object - ms_resolution = ms.resolution() - ms_resolution.plot() - """ - - boxplot_kwargs = {} if boxplot_kwargs is None else boxplot_kwargs.copy() - stripplot_kwargs = {} if stripplot_kwargs is None else stripplot_kwargs.copy() - savefig_settings = {} if savefig_settings is None else savefig_settings.copy() - - if ax is None: - fig,ax = plt.subplots(figsize=figsize) - - data = pd.DataFrame(columns=['Resolution','Label']) - - for resolution in self.resolution_list: - for value in resolution.resolution: - data.loc[len(data),['Resolution','Label']] = [value,resolution.label] - - if 'whis' in boxplot_kwargs: - boxplot_whis = boxplot_kwargs.pop('whis') - if 'width' in boxplot_kwargs: - boxplot_width = boxplot_kwargs.pop('width') - if 'dodge' in boxplot_kwargs: - boxplot_dodge = boxplot_kwargs.pop('dodge') - if 'palette' in boxplot_kwargs: - boxplot_palette = boxplot_kwargs.pop('palette') - - if 'size' in stripplot_kwargs: - stripplot_size = stripplot_kwargs.pop('size') - if 'color' in stripplot_kwargs: - stripplot_color = stripplot_kwargs.pop('color') - if 'alpha' in stripplot_kwargs: - stripplot_alpha = stripplot_kwargs.pop('alpha') - if 'dodge' in stripplot_kwargs: - stripplot_dodge = stripplot_kwargs.pop('dodge') - - sns.boxplot(data,x='Resolution',y='Label',hue='Label',whis=boxplot_whis, width=boxplot_width, dodge=boxplot_dodge, palette=boxplot_palette, ax=ax, **boxplot_kwargs) - sns.stripplot(data, x="Resolution", y="Label",size=stripplot_size,color=stripplot_color,alpha=stripplot_alpha,dodge=stripplot_dodge,ax=ax,**stripplot_kwargs) - - if ylabel: - ax.set(ylabel=ylabel) - else: - ax.set(ylabel="") - - if xlabel: - ax.set(xlabel=xlabel) - else: - ax.set(xlabel=f"Resolution [{self.time_unit}]") - - if not legend: - ax.legend().set_visible(False) - - # Tweak the visual presentation - ax.xaxis.grid(True) - sns.despine(trim=True, left=True) - - if 'fig' in locals(): - if 'path' in savefig_settings: - plotting.savefig(fig, settings=savefig_settings) - return fig, ax - else: - return ax - - def describe(self): - '''Describe the stats of the resolution list - - Returns - ------- - - resolution_dict : dict - Dictionary of relevant stats produced by `scipy.stats.describe `_ - - Examples - -------- - - ..jupyter-execute:: - import pyleoclim as pyleo - - co2ts = pyleo.utils.load_dataset('AACO2') - edc = pyleo.utils.load_dataset('EDC-dD') - ms = edc & co2ts # create MS object - ms_resolution = ms.resolution() - ms_resolution.plot() - - ''' - - resolution_dict = {} - - for resolution in self.resolution_list: - stats = st.describe(resolution.resolution)._asdict() - - median = np.median(resolution.resolution) - stats['median'] = median - - resolution_dict[resolution.label] = stats - - return resolution_dict \ No newline at end of file diff --git a/pyleoclim/core/multipleseries.py b/pyleoclim/core/multipleseries.py index e1677cb7..19b5abb0 100644 --- a/pyleoclim/core/multipleseries.py +++ b/pyleoclim/core/multipleseries.py @@ -11,7 +11,7 @@ from ..core.scalograms import MultipleScalogram from ..core.psds import MultiplePSD from ..core.multivardecomp import MultivariateDecomp -from ..core.multipleresolution import MultipleResolution +from ..core.resolutions import MultipleResolution import warnings import numpy as np @@ -2324,42 +2324,6 @@ def sel(self, value=None, time=None, tolerance=0): return ms_new - # def resolution(self, statistic='median'): - # ''' - # Extracts representative statistic for the resolution of each series in the object. - - # Parameters - # ---------- - # statistic : str, optional - # The statistic applied to the resolution array of each series. - # Possible values: 'mean' or 'median'. The default is 'median'. - - # Returns - # ------- - # res: NumPy array - # array containing the statistic of interest for all series. - - # Examples - # -------- - # .. jupyter-execute:: - - # co2ts = pyleo.utils.load_dataset('AACO2') - # edc = pyleo.utils.load_dataset('EDC-dD') - # ms = edc & co2ts # create MS object - # ms.convert_time_unit('kyr BP').resolution() - - # Note that the output is only meaningful if all constituent series have the same units. - # ''' - - # if statistic=='median': - # res = [np.median(ts.resolution().resolution) for ts in self.series_list] - # elif statistic=='mean': - # res = [np.mean(ts.resolution().resolution) for ts in self.series_list] - # else: - # raise ValueError('Unknown statistic',stacklevel=2) - - # return np.array(res) - def to_json(self, path=None): ''' Export the pyleoclim.MultipleSeries object to a json file @@ -2682,14 +2646,14 @@ def resolution(self,time_unit=None,verbose=True,statistic='median'): See Also -------- - pyleoclim.core.multipleresolution.MultipleResolution + pyleoclim.core.resolutions.MultipleResolution pyleoclim.core.series.Series.convert_time_unit Examples -------- - To create a resolution object, apply the .resolution() method to a Series object + To create a resolution object, apply the .resolution() method to a Series object with `statistic=None`. .. jupyter-execute:: @@ -2698,7 +2662,7 @@ def resolution(self,time_unit=None,verbose=True,statistic='median'): co2ts = pyleo.utils.load_dataset('AACO2') edc = pyleo.utils.load_dataset('EDC-dD') ms = edc & co2ts # create MS object - ms_resolution = ms.resolution() + ms_resolution = ms.resolution(statistic=None) Several methods are then available: @@ -2708,11 +2672,11 @@ def resolution(self,time_unit=None,verbose=True,statistic='median'): ms_resolution.describe() - A simple plot can be created using .plot() + A simple plot can be created using .summary_plot() .. jupyter-execute:: - ms_resolution.plot() + ms_resolution.summary_plot() """ if statistic=='median': @@ -2746,7 +2710,7 @@ def resolution(self,time_unit=None,verbose=True,statistic='median'): for series in series_list: resolution = series.resolution() resolution_list.append(resolution) - + res = MultipleResolution(resolution_list=resolution_list,time_unit=time_unit) else: raise ValueError('Unrecognized statistic, please use "mean", "median", or None') diff --git a/pyleoclim/core/resolution.py b/pyleoclim/core/resolutions.py similarity index 63% rename from pyleoclim/core/resolution.py rename to pyleoclim/core/resolutions.py index 1c59bf61..ac243c32 100644 --- a/pyleoclim/core/resolution.py +++ b/pyleoclim/core/resolutions.py @@ -460,4 +460,197 @@ def make_labels(self): else: time_header = f'{time_name_str}' - return time_header, value_header \ No newline at end of file + return time_header, value_header + +class MultipleResolution: + ''' MultipleResolution object + + MultipleResolution objects store time axis resolution information derived from MultipleSeries objects. + They are generated via the resolution method applied to a MultipleSeries object and contain methods relevant to the analysis of resolution information. + + See Also + -------- + + ''' + + def __init__(self,resolution_list,time_unit): + self.resolution_list = resolution_list + self.time_unit = time_unit + + def summary_plot(self,figsize=(10,8),xlabel=None,ylabel=None,legend=False,ax=None, + boxplot_whis=[0,100], boxplot_width=.6, boxplot_dodge=False,boxplot_palette='viridis', + stripplot_size=2,stripplot_color=".3",stripplot_alpha=.8,stripplot_dodge=False, log_scale = False, + boxplot_kwargs=None,stripplot_kwargs=None,savefig_settings=None): + """Summary plot showing distribution of resolutions from each resolution object as box plots with overlaid strip plots. + + Parameters + ---------- + + figsize : tuple, list + Size of the figure. + + xlabel : str + Label for the x axis. "Resolution [{time_unit}]" will be used by default. + + ylabel : str + Label for the y axis. Left empty by default. + + legend : bool + Whether or not to plot the legend. Default is False. + + ax : matplotlib.ax + The matplotlib axis onto which to return the figure. The default is None. + + boxplot_whis : float or pair of floats + If scalar, whiskers are drawn to the farthest datapoint within whis * IQR from the nearest hinge. + If a tuple, it is interpreted as percentiles that whiskers represent. Default is [0,100] + + boxplot_width : float + Width allotted to each element on the orient axis. + + boxplot_dodge : bool + Whether boxplot elements should be narrowed and shifted along the orient axis to eliminate overlap. Default is False. + + boxplot_palette : palette name, list, or dict + Colors to use for the different levels of the hue variable. + Should be something that can be interpreted by color_palette(), or a dictionary mapping hue levels to matplotlib colors. + Gets passed to seaborn.boxplot for details. + + stripplot_size : float + Size of stripplot markers. + + stripplot_color : str + Color for the stripplot markers. + + stripplot_alpha : float + Alpha for the stripplot markers. + + stripplot_dodge : bool + Whether stripplot elements should be narrowed and shifted along the orient axis to eliminate overlap. Default is False. + + log_scale : bool or number, or pair of bools or numbers + Set axis scale(s) to log. A single value sets the data axis for any numeric axes in the plot. + A pair of values sets each axis independently. Numeric values are interpreted as the desired base (default 10). + When None or False, seaborn defers to the existing Axes scale. + + boxplot_kwargs : dict + Dictionary of arguments for seaborn.boxplot. Arguments that are passed here will overwrite explicit arguments (e.g. whis, width, etc.). + + stripplot_kwargs : dict + Dictionary of argument for seaborn.stripplot. Arguments that are passed here will overwrite explicit arguments (e.g. size, color, etc.). + + savefig_settings : dictionary, optional + + the dictionary of arguments for pyleo.utils.plotting.savefig(); some notes below: + - "path" must be specified; it can be any existing or non-existing 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. + + Examples + -------- + .. jupyter-execute:: + import pyleoclim as pyleo + + co2ts = pyleo.utils.load_dataset('AACO2') + edc = pyleo.utils.load_dataset('EDC-dD') + ms = edc & co2ts # create MS object + ms_resolution = ms.resolution() + ms_resolution.plot() + """ + + boxplot_kwargs = {} if boxplot_kwargs is None else boxplot_kwargs.copy() + stripplot_kwargs = {} if stripplot_kwargs is None else stripplot_kwargs.copy() + savefig_settings = {} if savefig_settings is None else savefig_settings.copy() + + if ax is None: + fig,ax = plt.subplots(figsize=figsize) + + data = pd.DataFrame(columns=['Resolution','Label']) + + for resolution in self.resolution_list: + for value in resolution.resolution: + data.loc[len(data),['Resolution','Label']] = [value,resolution.label] + + if 'whis' in boxplot_kwargs: + boxplot_whis = boxplot_kwargs.pop('whis') + if 'width' in boxplot_kwargs: + boxplot_width = boxplot_kwargs.pop('width') + if 'dodge' in boxplot_kwargs: + boxplot_dodge = boxplot_kwargs.pop('dodge') + if 'palette' in boxplot_kwargs: + boxplot_palette = boxplot_kwargs.pop('palette') + if 'log_scale' in boxplot_kwargs: + log_scale = boxplot_kwargs.pop('log_scale') + + if 'size' in stripplot_kwargs: + stripplot_size = stripplot_kwargs.pop('size') + if 'color' in stripplot_kwargs: + stripplot_color = stripplot_kwargs.pop('color') + if 'alpha' in stripplot_kwargs: + stripplot_alpha = stripplot_kwargs.pop('alpha') + if 'dodge' in stripplot_kwargs: + stripplot_dodge = stripplot_kwargs.pop('dodge') + if 'log_scale' in stripplot_kwargs: + log_scale = stripplot_kwargs.pop('log_scale') + + sns.boxplot(data,x='Resolution',y='Label',hue='Label',whis=boxplot_whis,width=boxplot_width,dodge=boxplot_dodge,palette=boxplot_palette,log_scale=log_scale,ax=ax,**boxplot_kwargs) + sns.stripplot(data, x="Resolution", y="Label",size=stripplot_size,color=stripplot_color,alpha=stripplot_alpha,dodge=stripplot_dodge,ax=ax,log_scale=log_scale,**stripplot_kwargs) + + if ylabel: + ax.set(ylabel=ylabel) + else: + ax.set(ylabel="") + + if xlabel: + ax.set(xlabel=xlabel) + else: + ax.set(xlabel=f"Resolution [{self.time_unit}]") + + if not legend: + ax.legend().set_visible(False) + + # Tweak the visual presentation + ax.xaxis.grid(True) + sns.despine(trim=True, left=True) + + if 'fig' in locals(): + if 'path' in savefig_settings: + plotting.savefig(fig, settings=savefig_settings) + return fig, ax + else: + return ax + + def describe(self): + '''Describe the stats of the resolution list + + Returns + ------- + + resolution_dict : dict + Dictionary of relevant stats produced by `scipy.stats.describe `_ + + Examples + -------- + + ..jupyter-execute:: + import pyleoclim as pyleo + + co2ts = pyleo.utils.load_dataset('AACO2') + edc = pyleo.utils.load_dataset('EDC-dD') + ms = edc & co2ts # create MS object + ms_resolution = ms.resolution() + ms_resolution.plot() + + ''' + + resolution_dict = {} + + for resolution in self.resolution_list: + stats = st.describe(resolution.resolution)._asdict() + + median = np.median(resolution.resolution) + stats['median'] = median + + resolution_dict[resolution.label] = stats + + return resolution_dict \ No newline at end of file diff --git a/pyleoclim/core/series.py b/pyleoclim/core/series.py index ba1fb656..bae9a5f1 100644 --- a/pyleoclim/core/series.py +++ b/pyleoclim/core/series.py @@ -26,7 +26,7 @@ from ..core.coherence import Coherence from ..core.corr import Corr from ..core.surrogateseries import SurrogateSeries -from ..core.resolution import Resolution +from ..core.resolutions import Resolution import seaborn as sns import matplotlib.pyplot as plt @@ -4076,7 +4076,7 @@ def resolution(self): See Also -------- - pyleoclim.core.resolution.Resolution + pyleoclim.core.resolutions.Resolution Examples -------- From e24b1a07390a73bad0ce3db124c598b1f970009b Mon Sep 17 00:00:00 2001 From: Alexander James Date: Thu, 7 Mar 2024 10:38:09 -0800 Subject: [PATCH 28/29] trying a different seaborn version --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 4bec2cc3..c6ee45e2 100644 --- a/setup.py +++ b/setup.py @@ -31,7 +31,7 @@ def read(fname): "pandas==2.1.4", "kneed>=0.7.0", "statsmodels>=0.13.2", - "seaborn>=0.13.0", + "seaborn==0.13.0", "scikit-learn>=0.24.2", "pathos>=0.2.8", "tqdm>=4.61.2", From 71bf9f08e725e8ec85af47869019e0c780b71c79 Mon Sep 17 00:00:00 2001 From: Alexander James Date: Thu, 7 Mar 2024 11:00:49 -0800 Subject: [PATCH 29/29] remove log_scale option --- pyleoclim/core/resolutions.py | 19 +++++++------------ setup.py | 2 +- 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/pyleoclim/core/resolutions.py b/pyleoclim/core/resolutions.py index ac243c32..b5667525 100644 --- a/pyleoclim/core/resolutions.py +++ b/pyleoclim/core/resolutions.py @@ -479,7 +479,7 @@ def __init__(self,resolution_list,time_unit): def summary_plot(self,figsize=(10,8),xlabel=None,ylabel=None,legend=False,ax=None, boxplot_whis=[0,100], boxplot_width=.6, boxplot_dodge=False,boxplot_palette='viridis', - stripplot_size=2,stripplot_color=".3",stripplot_alpha=.8,stripplot_dodge=False, log_scale = False, + stripplot_size=2,stripplot_color=".3",stripplot_alpha=.8,stripplot_dodge=False, boxplot_kwargs=None,stripplot_kwargs=None,savefig_settings=None): """Summary plot showing distribution of resolutions from each resolution object as box plots with overlaid strip plots. @@ -528,11 +528,6 @@ def summary_plot(self,figsize=(10,8),xlabel=None,ylabel=None,legend=False,ax=Non stripplot_dodge : bool Whether stripplot elements should be narrowed and shifted along the orient axis to eliminate overlap. Default is False. - log_scale : bool or number, or pair of bools or numbers - Set axis scale(s) to log. A single value sets the data axis for any numeric axes in the plot. - A pair of values sets each axis independently. Numeric values are interpreted as the desired base (default 10). - When None or False, seaborn defers to the existing Axes scale. - boxplot_kwargs : dict Dictionary of arguments for seaborn.boxplot. Arguments that are passed here will overwrite explicit arguments (e.g. whis, width, etc.). @@ -579,8 +574,8 @@ def summary_plot(self,figsize=(10,8),xlabel=None,ylabel=None,legend=False,ax=Non boxplot_dodge = boxplot_kwargs.pop('dodge') if 'palette' in boxplot_kwargs: boxplot_palette = boxplot_kwargs.pop('palette') - if 'log_scale' in boxplot_kwargs: - log_scale = boxplot_kwargs.pop('log_scale') + # if 'log_scale' in boxplot_kwargs: + # log_scale = boxplot_kwargs.pop('log_scale') if 'size' in stripplot_kwargs: stripplot_size = stripplot_kwargs.pop('size') @@ -590,11 +585,11 @@ def summary_plot(self,figsize=(10,8),xlabel=None,ylabel=None,legend=False,ax=Non stripplot_alpha = stripplot_kwargs.pop('alpha') if 'dodge' in stripplot_kwargs: stripplot_dodge = stripplot_kwargs.pop('dodge') - if 'log_scale' in stripplot_kwargs: - log_scale = stripplot_kwargs.pop('log_scale') + # if 'log_scale' in stripplot_kwargs: + # log_scale = stripplot_kwargs.pop('log_scale') - sns.boxplot(data,x='Resolution',y='Label',hue='Label',whis=boxplot_whis,width=boxplot_width,dodge=boxplot_dodge,palette=boxplot_palette,log_scale=log_scale,ax=ax,**boxplot_kwargs) - sns.stripplot(data, x="Resolution", y="Label",size=stripplot_size,color=stripplot_color,alpha=stripplot_alpha,dodge=stripplot_dodge,ax=ax,log_scale=log_scale,**stripplot_kwargs) + sns.boxplot(data,x='Resolution',y='Label',hue='Label',whis=boxplot_whis,width=boxplot_width,dodge=boxplot_dodge,palette=boxplot_palette,ax=ax,**boxplot_kwargs) + sns.stripplot(data, x="Resolution", y="Label",size=stripplot_size,color=stripplot_color,alpha=stripplot_alpha,dodge=stripplot_dodge,ax=ax,**stripplot_kwargs) if ylabel: ax.set(ylabel=ylabel) diff --git a/setup.py b/setup.py index c6ee45e2..a0eb6d37 100644 --- a/setup.py +++ b/setup.py @@ -31,7 +31,7 @@ def read(fname): "pandas==2.1.4", "kneed>=0.7.0", "statsmodels>=0.13.2", - "seaborn==0.13.0", + "seaborn==0.12.2", "scikit-learn>=0.24.2", "pathos>=0.2.8", "tqdm>=4.61.2",