diff --git a/pyleoclim/tests/examples.py b/pyleoclim/tests/examples.py index 271a2470..6dbd5e5e 100644 --- a/pyleoclim/tests/examples.py +++ b/pyleoclim/tests/examples.py @@ -18,4 +18,5 @@ def load_dataset(name, **kws): ts = pyleo.utils.load_dataset('LR04') ts5k = ts.resample('5ka').mean() fig, ax = ts.plot(invert_yaxis='True') -ts5k.plot(ax=ax,color='C1') \ No newline at end of file +ts5k.plot(ax=ax,color='C1') +pyleo.closefig(fig) \ No newline at end of file diff --git a/pyleoclim/tests/test_core_EnsembleSeries.py b/pyleoclim/tests/test_core_EnsembleSeries.py index 2234d2d1..4963ce01 100644 --- a/pyleoclim/tests/test_core_EnsembleSeries.py +++ b/pyleoclim/tests/test_core_EnsembleSeries.py @@ -211,6 +211,7 @@ def test_histplot_t0(self): ts_ens = pyleo.EnsembleSeries(series_list) ts_ens.histplot() + pyleo.closefig() class TestUIEnsembleSeriesDistplot(): def test_histplot_t0(self): @@ -230,3 +231,4 @@ def test_histplot_t0(self): ts_ens = pyleo.EnsembleSeries(series_list) ts_ens.histplot() + pyleo.closefig() diff --git a/pyleoclim/tests/utils/test_datasets.py b/pyleoclim/tests/utils/test_datasets.py index 0f306c46..c6524376 100644 --- a/pyleoclim/tests/utils/test_datasets.py +++ b/pyleoclim/tests/utils/test_datasets.py @@ -1,8 +1,8 @@ -# from pyleoclim.utils import load_dataset import pyleoclim as pyleo import pytest from pyleoclim.utils import datasets +# Datasets tested in this file TEST_DATASETS = [ 'SOI', 'NINO3', @@ -14,30 +14,37 @@ ] def test_load_datasets_metadata(): - """test loading all metadata for all datasets""" + """Test loading all metadata for all datasets""" meta = datasets.load_datasets_metadata() assert isinstance(meta, dict) +def test_load_datasets_metadata_with_path(): + """Test loading all metadata using specific path""" + meta = datasets.load_datasets_metadata(path=datasets.METADATA_PATH) + assert isinstance(meta, dict) + def test_available_dataset_names(): - """test getting available dataset names""" + """Test getting available dataset names""" names = datasets.available_dataset_names() assert len(names) > 0 @pytest.mark.parametrize('name', TEST_DATASETS) def test_get_metadata(name): + """Test getting metdata for the test datasets""" meta = datasets.get_metadata(name) assert isinstance(meta, dict) def test_get_metadata_invalid_name(): - """ensure error is raised with an invalid dataset name""" + """Test getting metadata using an invalid name. Ensure error is raised.""" with pytest.raises(RuntimeError, match='Metadata not found'): datasets.get_metadata('invalid_name') @pytest.mark.parametrize('name', TEST_DATASETS) def test_load_dataset(name): + """Test loading datasets""" ts = datasets.load_dataset(name) assert isinstance(ts, pyleo.Series) diff --git a/pyleoclim/utils/datasets.py b/pyleoclim/utils/datasets.py index 71b9f3dc..87c84b51 100644 --- a/pyleoclim/utils/datasets.py +++ b/pyleoclim/utils/datasets.py @@ -22,6 +22,16 @@ def load_datasets_metadata(path=METADATA_PATH): Returns ------- Dictionary of sample dataset metadata + + Examples + ------- + >>> from pyleoclim.utils.datasets import load_datasets_metadata + Load the metadata yaml file (with the default path) + >>> metadata = load_datasets_metadata() + Alternately, if you have a new metadata file, you can load it directly using + this method as well. + >>> metadata = load_datasets_metadata(path='path/to/metadata.yml') + """ with open(path, "r") as stream: try: @@ -31,7 +41,18 @@ def load_datasets_metadata(path=METADATA_PATH): def available_dataset_names(): - """Helper function to easily see what datasets are available to load""" + """Helper function to easily see what datasets are available to load + + Returns + ------- + List of datasets available via the `load_dataset` method. + + Examples + -------- + >>> from pyleoclim.utils.datasets import available_dataset_names + >>> available_dataset_names() + + """ meta = load_datasets_metadata() return list(meta.keys()) @@ -48,6 +69,11 @@ def get_metadata(name): Returns ------- Dictionary of metadata for this dataset + + Examples + -------- + >>> from pyleoclim.utils.datasets import get_metadata + >>> meta = get_metadata('LR04') """ all_metadata = load_datasets_metadata() metadata = all_metadata.get(name, None) @@ -58,6 +84,7 @@ def get_metadata(name): def load_dataset(name): """Load example dataset given the nickname + Note: Available datasets can be seen via `available_dataset_names` Parameters ---------- @@ -67,6 +94,11 @@ def load_dataset(name): Returns ------- pyleoclim_util.Series of the dataset + + Examples + -------- + >>> from pyleoclim.utils.datasets import load_dataset + >>> pyleo_series = load_dataset('LR04') """ # load the metadata for this dataset metadata = get_metadata(name) diff --git a/pyleoclim/utils/tsbase.py b/pyleoclim/utils/tsbase.py index ca4e4057..3600c07a 100644 --- a/pyleoclim/utils/tsbase.py +++ b/pyleoclim/utils/tsbase.py @@ -30,6 +30,39 @@ MATCH_GA = frozenset(['ga', 'gy', 'gyr', 'gyrs']) def time_unit_to_datum_exp_dir(time_unit, time_name=None, verbose=False): + """Convert time unit (yr, ka, ma, etc) to a datum, exponent, direction + triplet. Based on the time_unit (and optionally, the time_name) the datum + (year zero), exponent (10^x year units), and direction (prograde/retrograde) + can be inferred. A verbose option is included here for users who want to + confirm the resulting inference. + + Parameters + ---------- + time_unit: str + Time unit indicates the major unit of time. Examples: annum (yr), + kiloyear (ka, ky), milayear (ma, my), gigayear (ga, gy) + time_name: str + (Optional) If 'age', direction is always 'retrograde'. Defaults to None, + which is effectively unused. + verbose: bool + (Optional) If True, includes a print statement explaining the + conversion. + + Returns + ------- + datum : int, optional + origin point for the time scale. + exponent : int, optional + Base-10 exponent for year multiplier. Dates in kyr should use 3, dates in Myr should use 6, etc. + direction: str + Direction of time flow, 'prograde' or 'retrograde'. + + Examples + -------- + >>> from pyleoclim.utils.tsbase import time_unit_to_datum_exp_dir + >>> (datum, exponent, direction) = time_unit_to_datum_exp_dir(time_unit) + (1950, 3, 'retrograde') + """ tu = time_unit.lower().split() @@ -78,20 +111,48 @@ def time_unit_to_datum_exp_dir(time_unit, time_name=None, verbose=False): direction = 'retrograde' if verbose: - print(f'Provided time medata translated to {direction} flow, 10^{exponent} year units, and year {datum} datum') - + print(f'Provided time metadata translated to {direction} flow, 10^{exponent} year units, and year {datum} datum') + return (datum, exponent, direction) def convert_datetime_index_to_time(datetime_index, time_unit, time_name): - """ - Convert a DatetimeIndex to time in a given unit. - + """ Convert a Pandas DatetimeIndex into a numpy array of floats. + The general formula is: datetime_index = datum +/- time*10**exponent where we assume ``time`` to use the Gregorian calendar. If dealing with other calendars, then conversions need to happen before reaching pyleoclim. + + Parameters + ---------- + datetime_index: pd.DatetimeIndex + Index to covert to floats + time_unit: str + Time unit indicates the major unit of time. Examples: annum (yr), + kiloyear (ka, ky), milayear (ma, my), gigayear (ga, gy) + time_name: str + If 'age', direction is always 'retrograde'. + + Returns + ------- + np.array((float,)) of converted times + + Examples + -------- + >>> from pyleoclim.utils.tsbase import convert_datetime_index_to_time + >>> time_unit = 'ga' + >>> time_name = None + >>> dti = pd.date_range("2018-01-01", periods=5, freq="Y", unit='s') + >>> df = pd.DataFrame(np.array(range(5)), index=dti) + >>> time = convert_datetime_index_to_time( + df.index, + time_unit, + time_name=time_name, + ) + np.array([-6.89965777e-08, -6.99965777e-08, -7.09993155e-08, -7.19965777e-08, -7.29965777e-08]) + """ datum, exponent, direction = time_unit_to_datum_exp_dir(time_unit, time_name) if direction == 'prograde':