diff --git a/argopy/fetchers.py b/argopy/fetchers.py index 531923a23..280fdde49 100755 --- a/argopy/fetchers.py +++ b/argopy/fetchers.py @@ -926,7 +926,7 @@ def plot(self, ptype: str = "trajectory", **kwargs): Calling this method will automatically trigger a call to the :class:`argopy.DataFetcher.load` method. """ - self.load() + # self.load() if ptype in ["dac", "institution"]: if "institution" not in self.index: self.to_index(full=True) diff --git a/argopy/plot/argo_colors.py b/argopy/plot/argo_colors.py index 38f4c701b..8daddb8af 100644 --- a/argopy/plot/argo_colors.py +++ b/argopy/plot/argo_colors.py @@ -81,7 +81,7 @@ def __init__(self, name: str = "Set1", N: int = None): "ticklabels": ['PROBABLE', 'CONFIRMED', 'REGISTERED', 'OPERATIONAL', 'INACTIVE', 'CLOSED'], }, "qc": { - "name": "Quality control flag scale", + "name": "Quality control flag scale for measurements", "aka": ["qc_flag", "quality_control", "quality_control_flag", "quality_control_flag_scale"], "constructor": self._colormap_quality_control_flag, "ticks": np.arange(0, 9 + 1), @@ -104,6 +104,19 @@ def __init__(self, name: str = "Set1", N: int = None): "ticklabels": ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"], }, + "pqc": { + "name": "Quality control flag scale for whole profiles", + "aka": ["pqc_flag", "profile_qc", "profile_quality_control_flag", "profile_quality_control_flag", "profile_quality_control_flag_scale"], + "constructor": self._colormap_profile_quality_control_flag, + "ticks": ["N", "A", "B", "C", "D", "E", "F"], + "ticklabels": ["No QC performed", + "100% of profile good", + "75% - 100% of profile good", + "50% - 75% of profile good", + "25% - 50% of profile good", + "0% - 25% of profile good", + "0% of profile good"] + }, } self.registered = self.name in self.list_valid_known_colormaps self._colormap = self.cmap @@ -270,6 +283,18 @@ def _colormap_quality_control_flag(self): ] return mcolors.LinearSegmentedColormap.from_list(self.definition['name'], clist, 10) + def _colormap_profile_quality_control_flag(self): + """Return a colormap for Profile QC flag""" + clist = ['#000000', + '#31FC03', + '#ADFC03', + '#FCBA03', + '#324CA8', + '#B22CC9', + '#FC1C03', + ] + return mcolors.LinearSegmentedColormap.from_list(self.definition['name'], clist, 7) + @property def cmap(self): """Discrete colormap as :class:`matplotlib.colors.LinearSegmentedColormap` diff --git a/argopy/plot/plot.py b/argopy/plot/plot.py index f3ec1055d..d5489195c 100644 --- a/argopy/plot/plot.py +++ b/argopy/plot/plot.py @@ -496,7 +496,10 @@ def guess_cmap(hue): if hue.lower() in ArgoColors().list_valid_known_colormaps: cmap = hue.lower() elif "qc" in hue.lower(): - cmap = "qc" + if "profile_" not in hue.lower(): + cmap = "qc" + else: + cmap = "pqc" elif "mode" in hue.lower(): cmap = "data_mode" elif "status_code" in hue.lower(): @@ -789,7 +792,7 @@ def get_vlabel(this_ds, this_v): # ax.set_facecolor(bgcolor) if cbar: - cbar = fig.colorbar(m, shrink=0.9, extend="both", ax=ax) + cbar = fig.colorbar(m, shrink=0.9, ax=ax) cbar.ax.set_ylabel(get_vlabel(ds, this_param), rotation=90) ylim = ax.get_ylim() diff --git a/argopy/stores/float/argo_float.py b/argopy/stores/float/argo_float.py index df7838abb..d184a32fc 100644 --- a/argopy/stores/float/argo_float.py +++ b/argopy/stores/float/argo_float.py @@ -77,8 +77,9 @@ class ArgoFloat(FloatStore): af.plot.trajectory() af.plot.trajectory(figsize=(18,18), padding=[1, 5]) af.plot.map('TEMP', pres=450, cmap='Spectral_r') - af.plot.map('DATA_MODE', cbar=False, legend=True) - af.plot.scatter('PSAL') + af.plot.map('DATA_MODE') + af.plot.scatter('TEMP') + af.plot.scatter('PSAL_QC') af.plot.scatter('DOXY', ds='Sprof') af.plot.scatter('MEASUREMENT_CODE', ds='Rtraj') diff --git a/argopy/stores/float/implementations/plot.py b/argopy/stores/float/implementations/plot.py index 023eb9d83..05a67f62c 100644 --- a/argopy/stores/float/implementations/plot.py +++ b/argopy/stores/float/implementations/plot.py @@ -1,8 +1,8 @@ import numpy as np from typing import Any -from ....plot import scatter_plot, scatter_map -from ....utils.lists import list_multiprofile_file_variables, list_bgc_s_variables +from ....plot import scatter_plot, scatter_map, ArgoColors +from ....utils import list_multiprofile_file_variables, list_bgc_s_variables, to_list from ..extensions import ArgoFloatPlotProto @@ -24,7 +24,7 @@ class ArgoFloatPlot(ArgoFloatPlotProto): af.plot.map('TEMP', pres=450, cmap='Spectral_r') - af.plot.map('DATA_MODE', cbar=False, legend=True) + af.plot.map('DATA_MODE') af.plot.scatter('PSAL') @@ -143,8 +143,11 @@ def map( from argopy import ArgoFloat af = ArgoFloat(wmo) - af.plot.map('TEMP', pres=450, cmap='Spectral_r') - af.plot.map('DATA_MODE', cbar=False, legend=True) + + af.plot.map('TEMP') # Plot pressure level closest to 0 by default + af.plot.map('PSAL', pres=450.) + af.plot.map('PROFILE_TEMP_QC') + af.plot.map('DATA_MODE') """ if ds == "prof" and param not in list_multiprofile_file_variables(): @@ -175,12 +178,29 @@ def map( N_LEVELS=0 ) + # Check if param will be plotted using a discrete and known Argo colormap + discrete, cmap = False, 'Spectral_r' + if "qc" in param.lower() or "mode" in param.lower(): + discrete, cmap = True, None # Let scatter_map guess cmap + + if "N_LEVELS" in self._obj.dataset(ds)[param].dims: + legend_title = "%s @ %s PRES level in [%0.1f-%0.1f] db" % ( + param, + select, + bins[0], + bins[1], + ) + else: + legend_title = param + default_kwargs = { "x": "LONGITUDE", "y": "LATITUDE", "hue": param, - "legend": False, - "cbar": True, + "cmap": cmap, + "legend": True if discrete else False, + "cbar": False if discrete else True, + "legend_title": legend_title, } this_kwargs = {**default_kwargs, **kwargs} @@ -189,7 +209,7 @@ def map( return fig, ax, hdl def scatter(self, param, ds="prof", **kwargs) -> Any: - """Scatter plot for one dataset parameter + """Scatter plot for a 2-dimensional dataset parameter This method creates a 2D scatter plot with the :meth:`argopy.plot.scatter_plot` method. @@ -207,6 +227,7 @@ def scatter(self, param, ds="prof", **kwargs) -> Any: - :class:`matplotlib.figure.Figure` - :class:`matplotlib.axes.Axes` - list of patches + - :class:`matplotlib.colorbar.Colorbar` Examples -------- @@ -214,7 +235,8 @@ def scatter(self, param, ds="prof", **kwargs) -> Any: from argopy import ArgoFloat af = ArgoFloat(wmo) - af.plot.scatter('PSAL') + af.plot.scatter('TEMP') + af.plot.scatter('PSAL_QC') # Appropriate colormap automatically selected af.plot.scatter('DOXY', ds='Sprof') af.plot.scatter('MEASUREMENT_CODE', ds='Rtraj') @@ -238,9 +260,22 @@ def scatter(self, param, ds="prof", **kwargs) -> Any: default_kwargs = {"this_x": "JULD", "cbar": True} this_kwargs = {**default_kwargs, **kwargs} + if "_QC" in param: + mycolors = ArgoColors('qc', 9) + this_kwargs.update({ + "cmap": mycolors.cmap, + "vmin": 0, + "vmax": 9+1, + }) + if this_kwargs["cbar"]: fig, ax, m, cbar = scatter_plot(this_ds, param, **this_kwargs) ax.set_title(self._default_title) + + if "_QC" in param: + cbar.set_ticks(to_list([k + 0.5 for k in mycolors.ticklabels.keys()])) + cbar.set_ticklabels(to_list([k for k in mycolors.ticklabels.values()])) + return fig, ax, m, cbar else: fig, ax, m = scatter_plot(this_ds, param, **this_kwargs) diff --git a/argopy/stores/index/implementations/plot.py b/argopy/stores/index/implementations/plot.py index 396e176ed..802961612 100644 --- a/argopy/stores/index/implementations/plot.py +++ b/argopy/stores/index/implementations/plot.py @@ -46,6 +46,19 @@ class ArgoIndexPlot(ArgoIndexPlotProto): idx.plot.bar(by='dac') + .. code-block:: python + :caption: Full index vs query results + + from argopy import ArgoIndex + idx = ArgoIndex(index_file='bgc-s') + idx.query.params('CHLA') + + idx.plot.bar(by='profiler') # Plot query results (default) + + idx.plot.bar(by='profiler', index=True) # Force plot of full index + + + See Also -------- :class:`ArgoIndex.plot.trajectory`, :class:`ArgoIndex.plot.bar` diff --git a/argopy/tests/test_stores_float_plot.py b/argopy/tests/test_stores_float_plot.py index fa204c7b4..b619e893e 100644 --- a/argopy/tests/test_stores_float_plot.py +++ b/argopy/tests/test_stores_float_plot.py @@ -61,15 +61,18 @@ def test_plot_map_errors(self): with pytest.raises(ValueError): af.plot.map("NOT_A_BGC_PARAM", ds="Sprof") with pytest.raises(ValueError): - af.plot.map("DOXY", ds="prof") + af.plot.map("NOT_A_TRAJ_PARAM", ds="Rtraj") @requires_cartopy @pytest.mark.parametrize( "wmo", [VALID_WMO[0]], indirect=False, ids=[f"wmo={w}" for w in [VALID_WMO[0]]] ) - def test_plot_map(self, wmo): + @pytest.mark.parametrize( + "pres", [0., 200.], indirect=False, ids=[f"pres={p}" for p in [0., 200.]] + ) + def test_plot_map(self, wmo, pres): af = ArgoFloat(wmo, host=VALID_HOST, cache=True) - fig, ax, hdl = af.plot.map("TEMP", ds="prof") + fig, ax, hdl = af.plot.map("TEMP", pres=pres, ds="prof") assert isinstance(fig, mpl.figure.Figure) assert isinstance(ax, cartopy.mpl.geoaxes.GeoAxesSubplot) mpl.pyplot.close(fig) @@ -89,13 +92,16 @@ def test_plot_scatter_errors(self): @pytest.mark.parametrize( "cbar", [True, False], indirect=False, ids=[f"cbar={c}" for c in [True, False]] ) - def test_plot_scatter(self, wmo, cbar): + @pytest.mark.parametrize( + "param", ["TEMP", "TEMP_QC"], indirect=False, ids=[f"param={p}" for p in ["TEMP", "TEMP_QC"]] + ) + def test_plot_scatter(self, wmo, cbar, param): af = ArgoFloat(wmo, host=VALID_HOST, cache=True) if cbar: - fig, ax, m, cbar = af.plot.scatter("TEMP", ds="prof", cbar=cbar) + fig, ax, m, cbar = af.plot.scatter(param, ds="prof", cbar=cbar) else: - fig, ax, m = af.plot.scatter("TEMP", ds="prof", cbar=cbar) + fig, ax, m = af.plot.scatter(param, ds="prof", cbar=cbar) assert isinstance(fig, mpl.figure.Figure) assert isinstance(ax, mpl.axes.Axes) diff --git a/docs/_static/ArgoColors_pqc.png b/docs/_static/ArgoColors_pqc.png new file mode 100644 index 000000000..3a59c15e7 Binary files /dev/null and b/docs/_static/ArgoColors_pqc.png differ diff --git a/docs/_static/ArgoFloat_DATA_MODE.png b/docs/_static/ArgoFloat_DATA_MODE.png new file mode 100644 index 000000000..9cb76932f Binary files /dev/null and b/docs/_static/ArgoFloat_DATA_MODE.png differ diff --git a/docs/_static/ArgoFloat_MEASUREMENT_CODE.png b/docs/_static/ArgoFloat_MEASUREMENT_CODE.png new file mode 100644 index 000000000..3ab79c857 Binary files /dev/null and b/docs/_static/ArgoFloat_MEASUREMENT_CODE.png differ diff --git a/docs/_static/ArgoFloat_PROFILE_PSAL_QC.png b/docs/_static/ArgoFloat_PROFILE_PSAL_QC.png new file mode 100644 index 000000000..44ff285d3 Binary files /dev/null and b/docs/_static/ArgoFloat_PROFILE_PSAL_QC.png differ diff --git a/docs/_static/ArgoFloat_PSAL.png b/docs/_static/ArgoFloat_PSAL.png new file mode 100644 index 000000000..8c9429290 Binary files /dev/null and b/docs/_static/ArgoFloat_PSAL.png differ diff --git a/docs/_static/ArgoFloat_PSAL_QC.png b/docs/_static/ArgoFloat_PSAL_QC.png new file mode 100644 index 000000000..d6f95425b Binary files /dev/null and b/docs/_static/ArgoFloat_PSAL_QC.png differ diff --git a/docs/_static/ArgoFloat_TEMP.png b/docs/_static/ArgoFloat_TEMP.png new file mode 100644 index 000000000..fb0ddb271 Binary files /dev/null and b/docs/_static/ArgoFloat_TEMP.png differ diff --git a/docs/_static/ArgoFloat_TEMPscatter.png b/docs/_static/ArgoFloat_TEMPscatter.png new file mode 100644 index 000000000..23a56ee88 Binary files /dev/null and b/docs/_static/ArgoFloat_TEMPscatter.png differ diff --git a/docs/_static/ArgoFloat_trajectory.png b/docs/_static/ArgoFloat_trajectory.png new file mode 100644 index 000000000..91d72fcfd Binary files /dev/null and b/docs/_static/ArgoFloat_trajectory.png differ diff --git a/docs/_static/ArgoIndex_dac.png b/docs/_static/ArgoIndex_dac.png new file mode 100644 index 000000000..e2bdecdb6 Binary files /dev/null and b/docs/_static/ArgoIndex_dac.png differ diff --git a/docs/_static/ArgoIndex_institution.png b/docs/_static/ArgoIndex_institution.png new file mode 100644 index 000000000..461d66a0e Binary files /dev/null and b/docs/_static/ArgoIndex_institution.png differ diff --git a/docs/_static/ArgoIndex_profiler.png b/docs/_static/ArgoIndex_profiler.png new file mode 100644 index 000000000..6ac1c83bc Binary files /dev/null and b/docs/_static/ArgoIndex_profiler.png differ diff --git a/docs/_static/ArgoIndex_trajectory.png b/docs/_static/ArgoIndex_trajectory.png new file mode 100644 index 000000000..756f4377b Binary files /dev/null and b/docs/_static/ArgoIndex_trajectory.png differ diff --git a/docs/_static/ArgoIndex_trajectory_ph.png b/docs/_static/ArgoIndex_trajectory_ph.png new file mode 100644 index 000000000..9e53b71cc Binary files /dev/null and b/docs/_static/ArgoIndex_trajectory_ph.png differ diff --git a/docs/_static/bar_dac.png b/docs/_static/bar_dac.png index b7095319e..d7ce1e925 100644 Binary files a/docs/_static/bar_dac.png and b/docs/_static/bar_dac.png differ diff --git a/docs/_static/bar_profiler.png b/docs/_static/bar_profiler.png index 46cde56d4..b3970c7b4 100644 Binary files a/docs/_static/bar_profiler.png and b/docs/_static/bar_profiler.png differ diff --git a/docs/_static/bar_profiler_whitegrid.png b/docs/_static/bar_profiler_whitegrid.png new file mode 100644 index 000000000..2cad2dcfc Binary files /dev/null and b/docs/_static/bar_profiler_whitegrid.png differ diff --git a/docs/_static/scatter_map_Spectral.png b/docs/_static/scatter_map_Spectral.png index 520690c68..64ea8693f 100644 Binary files a/docs/_static/scatter_map_Spectral.png and b/docs/_static/scatter_map_Spectral.png differ diff --git a/docs/_static/scatter_map_datamode.png b/docs/_static/scatter_map_datamode.png index 74419323e..4c902fd43 100644 Binary files a/docs/_static/scatter_map_datamode.png and b/docs/_static/scatter_map_datamode.png differ diff --git a/docs/_static/scatter_map_deployment_status.png b/docs/_static/scatter_map_deployment_status.png index 8035a6296..d3766b92d 100644 Binary files a/docs/_static/scatter_map_deployment_status.png and b/docs/_static/scatter_map_deployment_status.png differ diff --git a/docs/_static/scatter_map_index.png b/docs/_static/scatter_map_index.png index 5ec3bd771..01db0156d 100644 Binary files a/docs/_static/scatter_map_index.png and b/docs/_static/scatter_map_index.png differ diff --git a/docs/_static/scatter_map_index_opts.png b/docs/_static/scatter_map_index_opts.png index 98431140f..13922911b 100644 Binary files a/docs/_static/scatter_map_index_opts.png and b/docs/_static/scatter_map_index_opts.png differ diff --git a/docs/_static/scatter_map_qcflag.png b/docs/_static/scatter_map_qcflag.png index ee0108a2e..5e56aaf8b 100644 Binary files a/docs/_static/scatter_map_qcflag.png and b/docs/_static/scatter_map_qcflag.png differ diff --git a/docs/_static/trajectory_sample.png b/docs/_static/trajectory_sample.png index d599016e0..6282f9e9b 100644 Binary files a/docs/_static/trajectory_sample.png and b/docs/_static/trajectory_sample.png differ diff --git a/docs/advanced-tools/stores/argofloat.rst b/docs/advanced-tools/stores/argofloat.rst index da391f245..13cee4166 100644 --- a/docs/advanced-tools/stores/argofloat.rst +++ b/docs/advanced-tools/stores/argofloat.rst @@ -101,3 +101,77 @@ The :class:`ArgoFloat` class is further used in **argopy** in the :class:`ArgoIn for a_float in idx.iterfloats(): ds = a_float.open_dataset('meta') print(a_float.WMO, ds['LAUNCH_DATE'].data) + +.. _argofloat-visu: + +Plotting features +----------------- +.. currentmodule:: argopy + +The :class:`ArgoFloat` class come with a :class:`ArgoFloat.plot` accessor than can take several methods to quickly visualize data from the float: + +Check all the detailed arguments on the API reference :class:`ArgoFloat.plot`. + +.. tabs:: + + .. tab:: Simple trajectory + + .. code-block:: python + + from argopy import ArgoFloat + af = ArgoFloat(6903262) + + af.plot.trajectory() + # af.plot.trajectory(figsize=(18,18), padding=[1, 5]) + + .. image:: ../../_static/ArgoFloat_trajectory.png + + .. tab:: Data along trajectory + + .. code-block:: python + + from argopy import ArgoFloat + af = ArgoFloat(6903262) + + af.plot.map('TEMP', pres=450, cmap='Spectral_r') + + .. image:: ../../_static/ArgoFloat_TEMP.png + + .. code-block:: python + + from argopy import ArgoFloat + af = ArgoFloat(6903262) + + af.plot.map('PROFILE_PSAL_QC') + + .. image:: ../../_static/ArgoFloat_PROFILE_PSAL_QC.png + + .. tab:: Data as a function of pressure + + .. code-block:: python + + from argopy import ArgoFloat + af = ArgoFloat(6903262) + + af.plot.scatter('TEMP') + + .. image:: ../../_static/ArgoFloat_TEMPscatter.png + + Plotting QC will automatically select the appropriate colormap: + + .. code-block:: python + + af.plot.scatter('PSAL_QC') + + .. image:: ../../_static/ArgoFloat_PSAL_QC.png + + Note that by default, variables are loaded from the `prof` netcdf dataset, but variables from other netcdf dataset can also be plotted if the appropriate dataset is indicated with the `ds` argument: + + .. code-block:: python + + from argopy import ArgoFloat + af = ArgoFloat(6903262) + + af.plot.scatter('MEASUREMENT_CODE', ds='Rtraj') + + .. image:: ../../_static/ArgoFloat_MEASUREMENT_CODE.png diff --git a/docs/advanced-tools/stores/argoindex.rst b/docs/advanced-tools/stores/argoindex.rst index 34ee22bcd..ee3275079 100644 --- a/docs/advanced-tools/stores/argoindex.rst +++ b/docs/advanced-tools/stores/argoindex.rst @@ -331,3 +331,79 @@ Two specific index variables are only available with BGC-Argo index files: ``PAR :okwarning: idx.query.parameter_data_mode({'BBP700': ['R', 'A'], 'DOXY': 'D'}, logical='or') + +.. _argoindex-visu: + +Plotting features +----------------- +.. currentmodule:: argopy + +The :class:`ArgoIndex` class come with a :class:`ArgoIndex.plot` accessor than can take several methods to quickly visualize data from the float. + +Check all the detailed arguments on the API reference :class:`ArgoIndex.plot`. + +.. tabs:: + + .. tab:: Float index trajectory + + .. code-block:: python + + from argopy import ArgoIndex + idx = ArgoIndex(index_file='bgc-s') + + idx.query.wmo('6904240') + idx.plot.trajectory() + + .. image:: ../../_static/ArgoIndex_trajectory.png + + Also with much more floats: + + .. code-block:: python + + from argopy import ArgoIndex + idx = ArgoIndex(index_file='bgc-s') + + idx.query.params('PH') + idx.plot.trajectory(set_global=True, + add_legend=False, + traj=False, + cbar=False, + markersize=12, + markeredgesize=0.1, + dpi=120, + figsize=(20,20)); + + .. image:: ../../_static/ArgoIndex_trajectory_ph.png + + .. tab:: Bar plot of index properties + + .. code-block:: python + + from argopy import ArgoIndex + idx = ArgoIndex(index_file='bgc-s') + idx.query.params('CHLA') + + idx.plot.bar(by='profiler') + + .. image:: ../../_static/ArgoIndex_profiler.png + + .. code-block:: python + + from argopy import ArgoIndex + idx = ArgoIndex(index_file='bgc-s') + idx.query.params('CHLA') + + idx.plot.bar(by='dac') + + .. image:: ../../_static/ArgoIndex_dac.png + + .. code-block:: python + + from argopy import ArgoIndex + idx = ArgoIndex(index_file='bgc-s') + idx.query.params('CHLA') + + idx.plot.bar(by='institution') + + .. image:: ../../_static/ArgoIndex_institution.png + diff --git a/docs/api-hidden.rst b/docs/api-hidden.rst index 920f1e2fc..75fc6b7a5 100644 --- a/docs/api-hidden.rst +++ b/docs/api-hidden.rst @@ -297,17 +297,6 @@ argopy.ArgoIndex.read_files argopy.ArgoIndex.records_per_wmo - argopy.ArgoIndex.search_wmo - argopy.ArgoIndex.search_cyc - argopy.ArgoIndex.search_wmo_cyc - argopy.ArgoIndex.search_tim - argopy.ArgoIndex.search_lat_lon - argopy.ArgoIndex.search_lat_lon_tim - argopy.ArgoIndex.search_params - argopy.ArgoIndex.search_parameter_data_mode - argopy.ArgoIndex.search_profiler_type - argopy.ArgoIndex.search_profiler_label - argopy.ArgoIndex.to_dataframe argopy.ArgoIndex.to_indexfile argopy.ArgoIndex.copy @@ -386,10 +375,6 @@ argopy.stores.float.spec.ArgoFloatProto argopy.stores.ArgoFloat - argopy.stores.ArgoFloat.plot - argopy.stores.ArgoFloat.plot.trajectory - argopy.stores.ArgoFloat.plot.map - argopy.stores.ArgoFloat.plot.scatter argopy.ArgoFloat.open_dataset argopy.ArgoFloat.ls_dataset argopy.ArgoFloat.path @@ -399,6 +384,11 @@ argopy.ArgoFloat.metadata argopy.ArgoFloat.N_CYCLES argopy.ArgoFloat.dac + + argopy.stores.ArgoFloat.plot + argopy.stores.ArgoFloat.plot.trajectory + argopy.stores.ArgoFloat.plot.map + argopy.stores.ArgoFloat.plot.scatter argopy.ArgoFloat.plot argopy.ArgoFloat.plot.trajectory argopy.ArgoFloat.plot.scatter diff --git a/docs/user-guide/working-with-argo-data/visualisation.rst b/docs/user-guide/working-with-argo-data/visualisation.rst index e408b0d76..d02b94572 100644 --- a/docs/user-guide/working-with-argo-data/visualisation.rst +++ b/docs/user-guide/working-with-argo-data/visualisation.rst @@ -8,8 +8,8 @@ Data visualisation .. contents:: :local: -From Data fetcher -***************** +From a DataFetcher +****************** The :class:`DataFetcher` come with a ``plot`` method to have a quick look to your data. This method can take *trajectory*, *profiler*, *dac* and *qc_altimetry* as arguments. All details are available in the :class:`DataFetcher.plot` class documentation. @@ -28,9 +28,9 @@ Trajectories .. code-block:: python - Adf = DataFetcher().float([6902745, 6902746]).load() - fig, ax = Adf.plot('trajectory') - fig, ax = Adf.plot() # Trajectory is the default plot + Adf = DataFetcher(src='gdac').float([6902745, 6902746]) + Adf.plot('trajectory') + Adf.plot() # Trajectory is the default plot .. image:: ../../_static/trajectory_sample.png @@ -41,8 +41,8 @@ It is also possible to create horizontal bar plots for histograms on some data p .. code-block:: python - Adf = DataFetcher().region([-80,-30,20,50,0,100,'2021-01','2021-08']).load() - fig, ax = Adf.plot('dac') + Adf = DataFetcher(src='gdac').region([-80,-30,20,50,0,100,'2021-01','2021-08']) + Adf.plot('dac') .. image:: ../../_static/bar_dac.png @@ -50,72 +50,32 @@ If you have `Seaborn `_ installed, you can change t .. code-block:: python - fig, ax = Adf.plot('profiler', style='whitegrid') + Adf.plot('profiler', style='whitegrid') -.. image:: ../../_static/bar_profiler.png +.. image:: ../../_static/bar_profiler_whitegrid.png -From ArgoFloat instance -*********************** +From an ArgoFloat +***************** .. currentmodule:: argopy -The :class:`ArgoFloat` class come with a :class:`ArgoFloat.plot` accessor than can take several methods to quickly visualize data from the float: - -.. code-block:: python - - from argopy import ArgoFloat - - wmo = 6902772 - - af = ArgoFloat(wmo) - - af.plot.trajectory() +The :class:`ArgoFloat` class come with a :class:`ArgoFloat.plot` accessor than can take several methods to quickly visualize data from the float. - af.plot.trajectory(figsize=(18,18), padding=[1, 5]) +Check the :ref:`dedicated documentation section ` or the detailed arguments on the API reference :class:`ArgoFloat.plot`. - af.plot.map('TEMP', pres=450, cmap='Spectral_r') +.. image:: ../../_static/ArgoFloat_TEMP.png - af.plot.map('DATA_MODE', cbar=False, legend=True) - af.plot.scatter('PSAL') - - af.plot.scatter('DOXY', ds='Sprof') - - af.plot.scatter('MEASUREMENT_CODE', ds='Rtraj') - - -Check all the detailed arguments on the API reference :class:`ArgoFloat.plot`. - -From ArgoIndex instance -************************ +From an ArgoIndex +***************** .. currentmodule:: argopy -The :class:`ArgoIndex` class come with a :class:`ArgoIndex.plot` accessor than can take several methods to quickly visualize data from the float: - -.. code-block:: python +The :class:`ArgoIndex` class come with a :class:`ArgoIndex.plot` accessor than can take several methods to quickly visualize data from the float. - from argopy import ArgoIndex +Check the :ref:`dedicated documentation section ` or the detailed arguments on the API reference :class:`ArgoIndex.plot`. - idx = ArgoIndex(index_file='bgc-s') - idx.query.params('CHLA') - - idx.plot.trajectory() - - idx.plot.trajectory(set_global=1, - add_legend=0, - traj=0, - cbar=False, - markersize=12, - markeredgesize=0.1, - dpi=120, - figsize=(20,20)); - - idx.plot.bar(by='profiler') - - idx.plot.bar(by='dac') - -Check all the detailed arguments on the API reference :class:`ArgoIndex.plot`. +.. image:: ../../_static/ArgoIndex_profiler.png Dashboards @@ -201,8 +161,11 @@ Examples: # similar to: DataFetcher().profile(WMO, CYC).dashboard() +Utilities +********* + Scatter Maps -************ +============ The :class:`argopy.plot.scatter_map` utility function is dedicated to making maps with Argo profile positions coloured according to specific variables: **a scatter map**. @@ -221,13 +184,13 @@ Let's import the usual suspects and some data to work with. ds = ArgoSet.data.argo.point2profile() df = ArgoSet.index - df_deployment = OceanOPSDeployments([-90, 0, 0, 90]).to_dataframe() + df_deployment = OceanOPSDeployments([-90, -10, 0, 90]).to_dataframe() And see in the examples below how it can be used and tuned. Default scatter map for trajectories -==================================== +------------------------------------ By default, the :func:`argopy.plot.scatter_map` function will try to plot a trajectory map, i.e. a map where profile points are of the same color for each floats and joined by a simple line. .. note:: @@ -256,7 +219,7 @@ Some options are available to customise the plot, for instance: .. code-block:: python - fig, ax = scatter_map(df, + fig, ax, _ = scatter_map(df, figsize=(10,6), set_global=True, markersize=2, @@ -269,7 +232,7 @@ Some options are available to customise the plot, for instance: Use predefined Argo Colors -========================== +-------------------------- The :class:`argopy.plot.scatter_map` function uses the :class:`ArgoColors` utility class to better resolve discrete colormaps of known variables. The colormap is automatically guessed using the ``hue`` argument. Here are some examples. .. tabs:: @@ -282,7 +245,7 @@ The :class:`argopy.plot.scatter_map` function uses the :class:`ArgoColors` utili scatter_map(ds, hue='DATA_MODE') - or more explicitly: + or more explicitly, this is equivalent to: .. code-block:: python @@ -298,13 +261,13 @@ The :class:`argopy.plot.scatter_map` function uses the :class:`ArgoColors` utili .. tab:: QC flag - Since QC flags are given for each measurements, we need to select a specific depth levels for this plot: + Since QC flags are given for each measurements, we need to select a specific depth levels for this plot. By default, we select data from the first vertical level along the `N_LEVELS` dimension. .. code-block:: python scatter_map(ds, hue='PSAL_QC') - using guess mode for arguments, or more explicitly: + using guess mode for arguments, or more explicitly, this is equivalent to: .. code-block:: python @@ -333,7 +296,7 @@ The :class:`argopy.plot.scatter_map` function uses the :class:`ArgoColors` utili Use any colormap -================ +---------------- Beyond the predefined set of Argo colors, one can use any colormap that can be discretesized. In the example below, we plot profile years of sampling using the reverse ``Spectral`` colormap: @@ -350,7 +313,7 @@ In the example below, we plot profile years of sampling using the reverse ``Spec Argo colors -*********** +=========== For your own plot methods, **argopy** provides the :class:`ArgoColors` utility class to better resolve discrete colormaps of known Argo variables. The class :class:`ArgoColors` is used to get a discrete colormap (available with the ``cmap`` attribute), as a :class:`matplotlib.colors.LinearSegmentedColormap`. @@ -388,6 +351,18 @@ The :ref:`Use predefined Argo Colors` section above gives examples of the availa ArgoColors('qc_flag').definition + .. tab:: Profile Quality control flag scale + + .. code-block:: python + + ArgoColors('pqc_flag') + + .. image:: ../../_static/ArgoColors_pqc.png + + .. ipython:: python + + ArgoColors('pqc_flag').definition + .. tab:: Deployment status .. code-block:: python diff --git a/docs/whats-new.rst b/docs/whats-new.rst index 3108a4d2c..59a34eab5 100644 --- a/docs/whats-new.rst +++ b/docs/whats-new.rst @@ -10,8 +10,15 @@ What's New Coming up next (unreleased) --------------------------- +Features and front-end API +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +- **New colormap in** :class:`ArgoColors` **for whole profile QC flags**. See the new documentation section on :ref:`Argo colors` for more. (:pr:`515`) by |gmaze|. + +- **Improved** :class:`ArgoFloat.plot` **methods**: now auto-select colormap, colorbar and legend settings depending on the parameter to plot. Check the documentation at: :ref:`argofloat-visu`. (:pr:`515`) by |gmaze|. + Internals ---------- +^^^^^^^^^ - **New post method for the** :class:`stores.httpstore` by |gmaze|.