diff --git a/glidertest/plots.py b/glidertest/plots.py index 6623d5b..1edc7a4 100644 --- a/glidertest/plots.py +++ b/glidertest/plots.py @@ -1299,3 +1299,42 @@ def plot_ioosqc(data, suspect_threshold=[25], fail_threshold=[50], title='', ax= if force_plot: plt.show() return fig, ax + +def plot_max_depth_per_profile(ds: xr.Dataset, bins= 20, ax = None, **kw: dict) -> tuple({plt.Figure, plt.Axes}): + """ + This function can be used to plot the maximum depth of each profile in a dataset. + + Parameters + ---------- + ds: xarray on OG1 format containing the profile number and the maximum depth. + bins: int, optional (default=20) + + Returns + ------- + One figure with two plots illustrating the max depth of each profile and a histogram of the max depths + + Original author + ---------------- + Till Moritz + """ + max_depths = tools.max_depth_per_profile(ds) + with plt.style.context(glidertest_style_file): + if ax is None: + fig, ax = plt.subplots(1, 2) + force_plot = True + else: + fig = plt.gcf() + force_plot = False + + ax[0].plot(max_depths.profile_num, max_depths,**kw) + ax[0].set_xlabel('Profile number') + ax[0].set_ylabel(f'Max depth ({max_depths.units})') + ax[0].set_title('Max depth per profile') + ax[1].hist(max_depths, bins=bins) + ax[1].set_xlabel(f'Max depth ({max_depths.units})') + ax[1].set_ylabel('Number of profiles') + ax[1].set_title('Histogram of max depth per profile') + [a.grid() for a in ax] + if force_plot: + plt.show() + return fig, ax \ No newline at end of file diff --git a/glidertest/tools.py b/glidertest/tools.py index 7f20a05..81f0099 100644 --- a/glidertest/tools.py +++ b/glidertest/tools.py @@ -480,3 +480,25 @@ def compute_global_range(ds: xr.Dataset, var='DOXY', min_val=-5, max_val=600): out_range = ds[var].where((ds[var]max_val )) return out_range.dropna(dim='N_MEASUREMENTS') +def max_depth_per_profile(ds: xr.Dataset): + """ + This function computes the maximum depth for each profile in the dataset + + Parameters + ---------- + ds: xarray on OG1 format containing at least depth and profile_number. Data + should not be gridded. + + Returns + ------- + max_depths: pandas dataframe containing the profile number and the maximum depth of that profile + + Original author + ---------------- + Till Moritz + """ + max_depths = ds.groupby('profile_num').apply(lambda x: x['DEPTH'].max()) + ### add the unit to the dataarray + max_depths.attrs['units'] = ds['DEPTH'].attrs['units'] + return max_depths + diff --git a/notebooks/demo.ipynb b/notebooks/demo.ipynb index bb22af5..08910f1 100644 --- a/notebooks/demo.ipynb +++ b/notebooks/demo.ipynb @@ -122,6 +122,17 @@ "plots.plot_glider_track(ds)" ] }, + { + "cell_type": "code", + "execution_count": null, + "id": "814f48b1", + "metadata": {}, + "outputs": [], + "source": [ + "# Basic plot of the maximum depth of the dataset per profile\n", + "plots.plot_max_depth_per_profile(ds)" + ] + }, { "cell_type": "code", "execution_count": null, @@ -936,7 +947,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.8" + "version": "3.13.0" } }, "nbformat": 4, diff --git a/tests/test_plots.py b/tests/test_plots.py index 990b068..d0015c5 100644 --- a/tests/test_plots.py +++ b/tests/test_plots.py @@ -124,4 +124,8 @@ def test_sop(): def test_plot_sampling_period_all(): ds = fetchers.load_sample_dataset() plots.plot_sampling_period_all(ds) - plots.plot_sampling_period(ds, variable='CHLA') \ No newline at end of file + plots.plot_sampling_period(ds, variable='CHLA') + +def test_plot_max_depth(): + ds = fetchers.load_sample_dataset() + plots.plot_max_depth_per_profile(ds) \ No newline at end of file diff --git a/tests/test_tools.py b/tests/test_tools.py index 5fbe29c..8ce7e20 100644 --- a/tests/test_tools.py +++ b/tests/test_tools.py @@ -58,3 +58,7 @@ def test_hyst(): def test_sop(): ds = fetchers.load_sample_dataset() tools.compute_global_range(ds, var='DOXY', min_val=-5, max_val=600) + +def test_maxdepth(): + ds = fetchers.load_sample_dataset() + tools.max_depth_per_profile(ds) \ No newline at end of file