├── _config.yml ├── MANIFEST.in ├── docs ├── api_reference │ ├── util │ │ ├── emso │ │ │ ├── emso_index.md │ │ │ ├── emso.md │ │ │ ├── get_info_fig.md │ │ │ ├── post_user_email.md │ │ │ ├── get_info_site.md │ │ │ ├── get_fig_map.md │ │ │ ├── get_info_platform_code.md │ │ │ ├── get_info_summary.md │ │ │ ├── get_info_metadata_id.md │ │ │ ├── get_info_parameter.md │ │ │ ├── get_info_fig_plot_argument.md │ │ │ ├── get_info_fig_plot.md │ │ │ ├── get_metadata.md │ │ │ ├── get_user_query.md │ │ │ ├── get_fig_data_interval.md │ │ │ ├── get_fig_line.md │ │ │ └── get_data.md │ │ ├── img_util │ │ │ ├── emso-map.png │ │ │ ├── emso_fig_map.png │ │ │ ├── widget-emso.png │ │ │ ├── widget-emso-qc.png │ │ │ ├── qc_widget-widget.png │ │ │ ├── emso_68422_TEMP_100.png │ │ │ ├── output-save-widget.png │ │ │ ├── iplot_location_example.png │ │ │ ├── emso_data_interval_TEMP.png │ │ │ └── iplot_timeseries_example.png │ │ ├── md_widget │ │ │ ├── widget_save.md │ │ │ ├── widget_emso.md │ │ │ ├── widget_qc.md │ │ │ └── widget_emso_qc.md │ │ ├── iplot │ │ │ ├── iplot_location.md │ │ │ └── iplot_timeseries.md │ │ ├── es_create_indexes.md │ │ ├── md5.md │ │ └── concat.md │ ├── waterframe │ │ ├── img_waterframe │ │ │ ├── plot-example.png │ │ │ ├── iplot-example.png │ │ │ ├── iplot_bar_polar.png │ │ │ ├── plot-hist-example.png │ │ │ ├── waterframe_imges.pptx │ │ │ ├── iplot_line-example.png │ │ │ ├── metadata-html-obsea.png │ │ │ ├── plot-timebar-example.png │ │ │ ├── waterframe_structure.png │ │ │ ├── data-intervals-example.png │ │ │ ├── iplot_scatter-example.png │ │ │ └── plot-timeseries-example.png │ │ ├── analysis │ │ │ ├── reduce_memory.md │ │ │ ├── use_only.md │ │ │ ├── rename.md │ │ │ ├── slice_time.md │ │ │ ├── drop.md │ │ │ ├── time_intervals.md │ │ │ ├── max.md │ │ │ ├── min.md │ │ │ ├── resample.md │ │ │ ├── corr.md │ │ │ └── info_metadata.md │ │ ├── output │ │ │ ├── to_json.md │ │ │ ├── to_pkl.md │ │ │ ├── to_csv.md │ │ │ ├── metadata_to_html.md │ │ │ ├── to_nc.md │ │ │ └── to_es.md │ │ ├── iplot │ │ │ ├── iplot_location.md │ │ │ ├── iplot_data_intervals.md │ │ │ ├── iplot_timeseries.md │ │ │ ├── iplot.md │ │ │ ├── iplot_bar_polar.md │ │ │ ├── iplot_line.md │ │ │ └── iplot_scatter.md │ │ ├── qc │ │ │ ├── qc_syntax_test.md │ │ │ ├── qc_range_test.md │ │ │ ├── qc_flat_test.md │ │ │ ├── qc_spike_test.md │ │ │ └── formula_cheat.md │ │ └── plot │ │ │ ├── plot.md │ │ │ ├── plot_timebar.md │ │ │ ├── plot_hist.md │ │ │ └── plot_timeseries.md │ └── input │ │ ├── read_nc_moist.md │ │ ├── read_nc.md │ │ └── from_emso.md ├── img_docs │ ├── logo.PNG │ ├── logos.png │ ├── mooda-header.jpg │ ├── mooda-header.png │ └── mooda-header_old.png ├── examples │ ├── data │ │ ├── TEMP.nc │ │ ├── TEMP.pkl │ │ ├── test_qc.pkl │ │ └── emodnet-esp-2020-01.7z │ ├── img_examples │ │ ├── no-qc.png │ │ ├── emso-map.png │ │ ├── qc-flat.png │ │ ├── fake-data.png │ │ ├── good-data.png │ │ ├── flat-range-qc.png │ │ ├── kd_timeseries.png │ │ ├── spanish-temp.png │ │ ├── widget-emso.png │ │ ├── qc_widget-plot1.png │ │ ├── qc_widget-plot2.png │ │ ├── qc_widget-plot3.png │ │ ├── qc_widget-plot4.png │ │ ├── qc_widget-plot5.png │ │ ├── widget-emso-qc.png │ │ ├── qc_widget-widget.png │ │ ├── output1-emso-widget.png │ │ ├── output2-emso-widget.png │ │ ├── qc_widget-output_wf.png │ │ ├── spike-range-flat-qc.png │ │ └── spanish-observatories.png │ ├── emso-qc-widget.md │ ├── index_examples.md │ ├── emso-widget.md │ ├── qc_widget.md │ ├── md5_dyfamed.md │ ├── emso-widget.ipynb │ ├── temp_spain_january_2019.md │ └── emso-qc-widget.ipynb ├── index_docs.md ├── installation │ └── installation.md ├── code_structure │ ├── rbardaji_mooda_docs.md │ ├── rbardaji_mooda.md │ └── rbardaji_mooda_mooda.md └── enhanced_qc.md ├── mooda ├── util │ ├── md_widgets │ │ ├── __init__.py │ │ └── widget_save.py │ ├── iplot │ │ ├── __init__.py │ │ ├── iplot_location.py │ │ └── iplot_timeseries.py │ ├── __init__.py │ ├── concat.py │ └── md5.py ├── waterframe │ ├── qc │ │ ├── qc_multiparameter_test.py │ │ ├── __init__.py │ │ ├── qc_syntax_test.py │ │ ├── qc_flat_test.py │ │ └── qc_replace.py │ ├── plot │ │ ├── __init__.py │ │ ├── plot.py │ │ ├── plot_hist.py │ │ └── plot_timebar.py │ ├── output │ │ ├── __init__.py │ │ ├── to_pkl.py │ │ ├── to_json.py │ │ ├── to_csv.py │ │ ├── metadata_to_html.py │ │ ├── to_nc.py │ │ └── html_templates │ │ │ └── metadata.html │ ├── analysis │ │ ├── copy.py │ │ ├── __init__.py │ │ ├── info_metadata.py │ │ ├── max_diff.py │ │ ├── rename.py │ │ ├── min.py │ │ ├── max.py │ │ ├── info_vocabulary.py │ │ ├── corr.py │ │ ├── drop.py │ │ ├── use_only.py │ │ ├── slice_time.py │ │ ├── time_intervals.py │ │ ├── pres2depth.py │ │ ├── asal_temp2dens.py │ │ ├── resample.py │ │ ├── psal2asal.py │ │ └── reduce_memory.py │ └── iplot │ │ ├── __init__.py │ │ ├── iplot_correlation_headmap.py │ │ ├── iplot_box.py │ │ ├── iplot_data_intervals.py │ │ ├── iplot_location.py │ │ ├── iplot_histogram.py │ │ ├── iplot_scatter_mapbox.py │ │ ├── iplot_candlestick.py │ │ └── iplot_scatter.py ├── input │ ├── __init__.py │ ├── read_pkl.py │ ├── read_json.py │ ├── read_df.py │ └── from_erddap.py └── __init__.py ├── requirements.txt ├── .gitignore ├── .github └── ISSUE_TEMPLATE │ ├── feature_request.md │ └── bug_report.md ├── LICENSE ├── README.md └── setup.py /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-slate -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include requirements.txt 2 | -------------------------------------------------------------------------------- /docs/api_reference/util/emso/emso_index.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/img_docs/logo.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rbardaji/mooda/HEAD/docs/img_docs/logo.PNG -------------------------------------------------------------------------------- /docs/img_docs/logos.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rbardaji/mooda/HEAD/docs/img_docs/logos.png -------------------------------------------------------------------------------- /docs/examples/data/TEMP.nc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rbardaji/mooda/HEAD/docs/examples/data/TEMP.nc -------------------------------------------------------------------------------- /docs/examples/data/TEMP.pkl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rbardaji/mooda/HEAD/docs/examples/data/TEMP.pkl -------------------------------------------------------------------------------- /docs/examples/data/test_qc.pkl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rbardaji/mooda/HEAD/docs/examples/data/test_qc.pkl -------------------------------------------------------------------------------- /docs/img_docs/mooda-header.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rbardaji/mooda/HEAD/docs/img_docs/mooda-header.jpg -------------------------------------------------------------------------------- /docs/img_docs/mooda-header.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rbardaji/mooda/HEAD/docs/img_docs/mooda-header.png -------------------------------------------------------------------------------- /mooda/util/md_widgets/__init__.py: -------------------------------------------------------------------------------- 1 | from .widget_qc import widget_qc 2 | from .widget_save import widget_save 3 | -------------------------------------------------------------------------------- /docs/img_docs/mooda-header_old.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rbardaji/mooda/HEAD/docs/img_docs/mooda-header_old.png -------------------------------------------------------------------------------- /docs/examples/img_examples/no-qc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rbardaji/mooda/HEAD/docs/examples/img_examples/no-qc.png -------------------------------------------------------------------------------- /docs/examples/img_examples/emso-map.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rbardaji/mooda/HEAD/docs/examples/img_examples/emso-map.png -------------------------------------------------------------------------------- /docs/examples/img_examples/qc-flat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rbardaji/mooda/HEAD/docs/examples/img_examples/qc-flat.png -------------------------------------------------------------------------------- /docs/examples/data/emodnet-esp-2020-01.7z: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rbardaji/mooda/HEAD/docs/examples/data/emodnet-esp-2020-01.7z -------------------------------------------------------------------------------- /docs/examples/img_examples/fake-data.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rbardaji/mooda/HEAD/docs/examples/img_examples/fake-data.png -------------------------------------------------------------------------------- /docs/examples/img_examples/good-data.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rbardaji/mooda/HEAD/docs/examples/img_examples/good-data.png -------------------------------------------------------------------------------- /docs/examples/img_examples/flat-range-qc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rbardaji/mooda/HEAD/docs/examples/img_examples/flat-range-qc.png -------------------------------------------------------------------------------- /docs/examples/img_examples/kd_timeseries.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rbardaji/mooda/HEAD/docs/examples/img_examples/kd_timeseries.png -------------------------------------------------------------------------------- /docs/examples/img_examples/spanish-temp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rbardaji/mooda/HEAD/docs/examples/img_examples/spanish-temp.png -------------------------------------------------------------------------------- /docs/examples/img_examples/widget-emso.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rbardaji/mooda/HEAD/docs/examples/img_examples/widget-emso.png -------------------------------------------------------------------------------- /docs/api_reference/util/img_util/emso-map.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rbardaji/mooda/HEAD/docs/api_reference/util/img_util/emso-map.png -------------------------------------------------------------------------------- /docs/examples/img_examples/qc_widget-plot1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rbardaji/mooda/HEAD/docs/examples/img_examples/qc_widget-plot1.png -------------------------------------------------------------------------------- /docs/examples/img_examples/qc_widget-plot2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rbardaji/mooda/HEAD/docs/examples/img_examples/qc_widget-plot2.png -------------------------------------------------------------------------------- /docs/examples/img_examples/qc_widget-plot3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rbardaji/mooda/HEAD/docs/examples/img_examples/qc_widget-plot3.png -------------------------------------------------------------------------------- /docs/examples/img_examples/qc_widget-plot4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rbardaji/mooda/HEAD/docs/examples/img_examples/qc_widget-plot4.png -------------------------------------------------------------------------------- /docs/examples/img_examples/qc_widget-plot5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rbardaji/mooda/HEAD/docs/examples/img_examples/qc_widget-plot5.png -------------------------------------------------------------------------------- /docs/examples/img_examples/widget-emso-qc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rbardaji/mooda/HEAD/docs/examples/img_examples/widget-emso-qc.png -------------------------------------------------------------------------------- /docs/api_reference/util/img_util/emso_fig_map.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rbardaji/mooda/HEAD/docs/api_reference/util/img_util/emso_fig_map.png -------------------------------------------------------------------------------- /docs/api_reference/util/img_util/widget-emso.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rbardaji/mooda/HEAD/docs/api_reference/util/img_util/widget-emso.png -------------------------------------------------------------------------------- /docs/examples/img_examples/qc_widget-widget.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rbardaji/mooda/HEAD/docs/examples/img_examples/qc_widget-widget.png -------------------------------------------------------------------------------- /mooda/waterframe/qc/qc_multiparameter_test.py: -------------------------------------------------------------------------------- 1 | """ Implementation of WaterFrame.qc_multiparameter_test() """ 2 | 3 | def qc_multiparameter_test() -------------------------------------------------------------------------------- /docs/api_reference/util/img_util/widget-emso-qc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rbardaji/mooda/HEAD/docs/api_reference/util/img_util/widget-emso-qc.png -------------------------------------------------------------------------------- /docs/examples/img_examples/output1-emso-widget.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rbardaji/mooda/HEAD/docs/examples/img_examples/output1-emso-widget.png -------------------------------------------------------------------------------- /docs/examples/img_examples/output2-emso-widget.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rbardaji/mooda/HEAD/docs/examples/img_examples/output2-emso-widget.png -------------------------------------------------------------------------------- /docs/examples/img_examples/qc_widget-output_wf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rbardaji/mooda/HEAD/docs/examples/img_examples/qc_widget-output_wf.png -------------------------------------------------------------------------------- /docs/examples/img_examples/spike-range-flat-qc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rbardaji/mooda/HEAD/docs/examples/img_examples/spike-range-flat-qc.png -------------------------------------------------------------------------------- /docs/api_reference/util/img_util/qc_widget-widget.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rbardaji/mooda/HEAD/docs/api_reference/util/img_util/qc_widget-widget.png -------------------------------------------------------------------------------- /docs/examples/img_examples/spanish-observatories.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rbardaji/mooda/HEAD/docs/examples/img_examples/spanish-observatories.png -------------------------------------------------------------------------------- /docs/api_reference/util/img_util/emso_68422_TEMP_100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rbardaji/mooda/HEAD/docs/api_reference/util/img_util/emso_68422_TEMP_100.png -------------------------------------------------------------------------------- /docs/api_reference/util/img_util/output-save-widget.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rbardaji/mooda/HEAD/docs/api_reference/util/img_util/output-save-widget.png -------------------------------------------------------------------------------- /docs/api_reference/util/img_util/iplot_location_example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rbardaji/mooda/HEAD/docs/api_reference/util/img_util/iplot_location_example.png -------------------------------------------------------------------------------- /mooda/util/iplot/__init__.py: -------------------------------------------------------------------------------- 1 | from .iplot_location import iplot_location 2 | from .iplot_timeseries import iplot_timeseries 3 | from .iplot_line import iplot_line 4 | -------------------------------------------------------------------------------- /docs/api_reference/util/img_util/emso_data_interval_TEMP.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rbardaji/mooda/HEAD/docs/api_reference/util/img_util/emso_data_interval_TEMP.png -------------------------------------------------------------------------------- /docs/api_reference/util/img_util/iplot_timeseries_example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rbardaji/mooda/HEAD/docs/api_reference/util/img_util/iplot_timeseries_example.png -------------------------------------------------------------------------------- /docs/api_reference/waterframe/img_waterframe/plot-example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rbardaji/mooda/HEAD/docs/api_reference/waterframe/img_waterframe/plot-example.png -------------------------------------------------------------------------------- /docs/api_reference/waterframe/img_waterframe/iplot-example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rbardaji/mooda/HEAD/docs/api_reference/waterframe/img_waterframe/iplot-example.png -------------------------------------------------------------------------------- /docs/api_reference/waterframe/img_waterframe/iplot_bar_polar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rbardaji/mooda/HEAD/docs/api_reference/waterframe/img_waterframe/iplot_bar_polar.png -------------------------------------------------------------------------------- /docs/api_reference/waterframe/img_waterframe/plot-hist-example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rbardaji/mooda/HEAD/docs/api_reference/waterframe/img_waterframe/plot-hist-example.png -------------------------------------------------------------------------------- /docs/api_reference/waterframe/img_waterframe/waterframe_imges.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rbardaji/mooda/HEAD/docs/api_reference/waterframe/img_waterframe/waterframe_imges.pptx -------------------------------------------------------------------------------- /docs/api_reference/waterframe/img_waterframe/iplot_line-example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rbardaji/mooda/HEAD/docs/api_reference/waterframe/img_waterframe/iplot_line-example.png -------------------------------------------------------------------------------- /docs/api_reference/waterframe/img_waterframe/metadata-html-obsea.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rbardaji/mooda/HEAD/docs/api_reference/waterframe/img_waterframe/metadata-html-obsea.png -------------------------------------------------------------------------------- /docs/api_reference/waterframe/img_waterframe/plot-timebar-example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rbardaji/mooda/HEAD/docs/api_reference/waterframe/img_waterframe/plot-timebar-example.png -------------------------------------------------------------------------------- /docs/api_reference/waterframe/img_waterframe/waterframe_structure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rbardaji/mooda/HEAD/docs/api_reference/waterframe/img_waterframe/waterframe_structure.png -------------------------------------------------------------------------------- /docs/api_reference/waterframe/img_waterframe/data-intervals-example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rbardaji/mooda/HEAD/docs/api_reference/waterframe/img_waterframe/data-intervals-example.png -------------------------------------------------------------------------------- /docs/api_reference/waterframe/img_waterframe/iplot_scatter-example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rbardaji/mooda/HEAD/docs/api_reference/waterframe/img_waterframe/iplot_scatter-example.png -------------------------------------------------------------------------------- /mooda/waterframe/plot/__init__.py: -------------------------------------------------------------------------------- 1 | from .plot_timeseries import plot_timeseries 2 | from .plot_timebar import plot_timebar 3 | from .plot_hist import plot_hist 4 | from .plot import plot 5 | -------------------------------------------------------------------------------- /docs/api_reference/waterframe/img_waterframe/plot-timeseries-example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rbardaji/mooda/HEAD/docs/api_reference/waterframe/img_waterframe/plot-timeseries-example.png -------------------------------------------------------------------------------- /mooda/waterframe/qc/__init__.py: -------------------------------------------------------------------------------- 1 | from .qc_flat_test import qc_flat_test 2 | from .qc_spike_test import qc_spike_test 3 | from .qc_range_test import qc_range_test 4 | from .qc_replace import qc_replace 5 | from .qc_syntax_test import qc_syntax_test 6 | -------------------------------------------------------------------------------- /mooda/input/__init__.py: -------------------------------------------------------------------------------- 1 | """ Input functions """ 2 | from .read_nc import read_nc 3 | from .read_pkl import read_pkl 4 | from .read_json import read_json 5 | from .from_erddap import from_erddap 6 | from .read_df import read_df 7 | from .read_dat_td_pati import read_dat_td_pati 8 | -------------------------------------------------------------------------------- /mooda/util/__init__.py: -------------------------------------------------------------------------------- 1 | """ Implementation of util """ 2 | from .concat import concat 3 | from .iplot import iplot_location, iplot_timeseries, iplot_line 4 | from .md5 import md5 5 | from .es_create_indexes import es_create_indexes 6 | from .md_widgets import widget_qc, widget_save 7 | -------------------------------------------------------------------------------- /mooda/waterframe/output/__init__.py: -------------------------------------------------------------------------------- 1 | """ Output functions from a WaterFrame """ 2 | from .to_nc import to_nc 3 | from .to_pkl import to_pkl 4 | from .to_json import to_json 5 | from .to_es import to_es 6 | from .metadata_to_html import metadata_to_html 7 | from .to_csv import to_csv 8 | -------------------------------------------------------------------------------- /mooda/__init__.py: -------------------------------------------------------------------------------- 1 | """ Implementation of mooda """ 2 | 3 | from .waterframe import WaterFrame 4 | from .input import read_nc, read_pkl, read_df, from_erddap, read_dat_td_pati 5 | from .util import concat, iplot_location, iplot_timeseries, md5, \ 6 | es_create_indexes, widget_qc, widget_save, iplot_line 7 | 8 | __version__ = '2.0.0' 9 | -------------------------------------------------------------------------------- /docs/index_docs.md: -------------------------------------------------------------------------------- 1 | # Documentation of mooda 2 | 3 | Index: 4 | 5 | * [API reference](api_reference/index_api_reference.md) 6 | * [GitHub and code structure](code_structure/rbardaji_mooda.md) 7 | * [Preferred parameter vocabulary](vocabulary.md) 8 | * [Installation](installation/installation.md) 9 | * [Examples](examples/index_examples.md) 10 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | elasticsearch>=7.8.0 2 | Flask>=1.1.2 3 | matplotlib>=3.3.0 4 | netCDF4>=1.5.3 5 | numpy>=1.19.0 6 | pandas>=1.0.5 7 | plotly>=4.9.0 8 | scikit-learn>=0.23.1 9 | scipy>=1.5.1 10 | xarray>=0.16.0 11 | nbformat>=5.0.7 12 | requests>=2.24.0 13 | ipywidgets>=7.6.3 14 | gsw 15 | statsmodels 16 | stockstats 17 | erddap-python 18 | scikit-learn>=0.23.1 19 | h5netcdf>=0.8.0 20 | -------------------------------------------------------------------------------- /mooda/waterframe/analysis/copy.py: -------------------------------------------------------------------------------- 1 | """ Implementation of WaterFrame.copy() """ 2 | from copy import deepcopy 3 | 4 | 5 | def copy(self): 6 | """ 7 | It returns a copy of the WaterFrame. 8 | 9 | Returns 10 | ------- 11 | new_wf: WaterFrame 12 | A copy of the WaterFrame. 13 | """ 14 | new_wf = deepcopy(self) 15 | return new_wf 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled python modules. 2 | *.pyc 3 | /__pycache__/ 4 | __pycache__ 5 | .ipynb_checkpoints 6 | 7 | # Setuptools distribution folder. 8 | /dist/ 9 | /build/ 10 | 11 | # Python egg metadata, regenerated from source files by setuptools. 12 | /*.egg-info 13 | 14 | # Visual Studio Code settings 15 | /.vscode/ 16 | 17 | # Test code 18 | /my-codes 19 | limit_memory.py 20 | desktop.ini 21 | # pylint 22 | .pylintrc 23 | .venv -------------------------------------------------------------------------------- /mooda/waterframe/plot/plot.py: -------------------------------------------------------------------------------- 1 | """ Implementation of WaterFrame.plot(**kwds)""" 2 | 3 | 4 | def plot(self, **kwds): 5 | """ 6 | It calls the pandas DataFrame.plot() method. 7 | 8 | Parameters 9 | ---------- 10 | **kwds: arguments 11 | pandas plot() arguments. 12 | 13 | Returns 14 | ------- 15 | axes : matplotlib.axes.Axes or numpy.ndarray of them 16 | """ 17 | axes = self.data.plot(**kwds) 18 | return axes 19 | -------------------------------------------------------------------------------- /docs/api_reference/util/emso/emso.md: -------------------------------------------------------------------------------- 1 | # mooda.EMSO(*user*=*''*, *password*=*''*, *token*=*''*) 2 | 3 | ## Reference 4 | 5 | Manage the EMSO ERIC API (http://api.emso.eu). 6 | 7 | ### Parameters 8 | 9 | * user: User for the EMSO ERIC API (str) 10 | * password: Password for the EMSO ERIC API (str) 11 | * token: Token for the EMSO ERIC API (str) 12 | 13 | ### Returns 14 | 15 | * emso: EMSO object 16 | 17 | ### Example 18 | 19 | ```python 20 | import mooda as md 21 | 22 | emso = md.EMSO() 23 | ``` 24 | 25 | Return to [Index](../../index_api_reference.md). -------------------------------------------------------------------------------- /docs/examples/emso-qc-widget.md: -------------------------------------------------------------------------------- 1 | # How to download EMSO data and perform QC data tests with a Jupyter Notebook Widget 2 | 3 | Este widget es la combinación de los widgets [mooda.widget_emso()](emso-widget.md) y [mooda.widget_qc()](qc-widget.md). 4 | 5 | ```python 6 | import mooda as md 7 | 8 | wf = md.WaterFrame() 9 | 10 | gui = md.widget_emso_qc(wf) 11 | gui 12 | ``` 13 | 14 | Output: 15 | 16 | ![EMSO map](./img_examples/emso-map.png) 17 | ![widget emso qc](./img_examples/widget-emso-qc.png) 18 | 19 | Return to the [Index of examples](index_examples.md). 20 | -------------------------------------------------------------------------------- /docs/api_reference/util/emso/get_info_fig.md: -------------------------------------------------------------------------------- 1 | # mooda.emso.get_info_fig() 2 | 3 | ## Reference 4 | 5 | Get the available figures. 6 | 7 | ### Returns 8 | 9 | * fig_list: List of available figures (List[str]) 10 | 11 | ### Example 12 | 13 | ```python 14 | import mooda as md 15 | 16 | emso = md.util.EMSO(user='LOGIN', password='PASSWORD') 17 | 18 | plot_list = emso.get_info_fig() 19 | print(*plot_list, sep='\n') 20 | ``` 21 | 22 | Output: 23 | 24 | ``` 25 | line 26 | data_interval 27 | map 28 | ``` 29 | 30 | Return to [Index](../../index_api_reference.md). 31 | -------------------------------------------------------------------------------- /docs/api_reference/util/emso/post_user_email.md: -------------------------------------------------------------------------------- 1 | # mooda.emso.post_user_email(*message*) 2 | 3 | ## Reference 4 | 5 | Send an email to help@emso-eu.org. 6 | 7 | ### Parameters 8 | 9 | * message: dict 10 | {'subject': 'Subject of the email', 11 | 'content': 'Content of the email'} 12 | 13 | ### Returns 14 | 15 | * response_message: Response from the API (str) 16 | 17 | ### Example 18 | 19 | ```python 20 | import mooda as md 21 | 22 | emso = md.util.EMSO(user='LOGIN', password='PASSWORD') 23 | 24 | 25 | ``` 26 | 27 | Return to [Index](../../index_api_reference.md). 28 | -------------------------------------------------------------------------------- /mooda/waterframe/iplot/__init__.py: -------------------------------------------------------------------------------- 1 | from .iplot_location import iplot_location 2 | from .iplot_timeseries import iplot_timeseries 3 | from .iplot import iplot 4 | from .iplot_scatter import iplot_scatter 5 | from .iplot_line import iplot_line 6 | from .iplot_data_intervals import iplot_data_intervals 7 | from .iplot_scatter_mapbox import iplot_scatter_mapbox 8 | from .iplot_bar_polar import iplot_bar_polar 9 | from .iplot_histogram import iplot_histogram 10 | from .iplot_candlestick import iplot_candlestick 11 | from .iplot_box import iplot_box 12 | from .iplot_correlation_headmap import iplot_correlation_headmap -------------------------------------------------------------------------------- /docs/api_reference/util/md_widget/widget_save.md: -------------------------------------------------------------------------------- 1 | # mooda.widget_save(*wf*) 2 | 3 | ## Reference 4 | 5 | It make a Jupyter notebook widget that allows to save the WaterFrame to a file. 6 | 7 | ### Parameters 8 | 9 | * wf: WaterFrame 10 | 11 | ### Returns 12 | 13 | * main_box: Jupyter notebook widget (ipwidgets.VBox) 14 | 15 | ## Example 16 | 17 | ```python 18 | import mooda as md 19 | 20 | wf = md.WaterFrame() 21 | 22 | gui = md.widget_save(wf) 23 | gui 24 | ``` 25 | 26 | Output: 27 | 28 | ![Output save widget](../img_util/output-save-widget.png) 29 | 30 | Return to [Index](../../index_api_reference.md). 31 | -------------------------------------------------------------------------------- /docs/api_reference/util/emso/get_info_site.md: -------------------------------------------------------------------------------- 1 | # mooda.emso.get_info_site() 2 | 3 | ## Reference 4 | 5 | Get available sites ('site') of the EMSO ERIC API. 6 | 7 | ### Returns 8 | 9 | * sites: List of 'site' (List[str]) 10 | 11 | ### Example 12 | 13 | ```python 14 | import mooda as md 15 | 16 | emso = md.util.EMSO(user='LOGIN', password='PASSWORD') 17 | 18 | sites = emso.get_info_site() 19 | print(*sites, sep='\n') 20 | ``` 21 | 22 | Output: 23 | 24 | ``` 25 | azores 26 | black-sea 27 | canarias 28 | hellenic 29 | ligurian 30 | obsea 31 | pap 32 | smartbay 33 | ``` 34 | 35 | Return to [Index](../../index_api_reference.md). 36 | -------------------------------------------------------------------------------- /mooda/waterframe/analysis/__init__.py: -------------------------------------------------------------------------------- 1 | from .copy import copy 2 | from .corr import corr 3 | from .min import min 4 | from .max import max 5 | from .use_only import use_only 6 | from .rename import rename 7 | from .max_diff import max_diff 8 | from .time_intervals import time_intervals 9 | from .resample import resample 10 | from .slice_time import slice_time 11 | from .info_metadata import info_metadata 12 | from .info_vocabulary import info_vocabulary 13 | from .drop import drop 14 | from .reduce_memory import reduce_memory 15 | from .pres2depth import pres2depth 16 | from .psal2asal import psal2asal 17 | from .asal_temp2dens import asal_temp2dens -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | 5 | --- 6 | 7 | **Is your feature request related to a problem? Please describe.** 8 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 9 | 10 | **Describe the solution you'd like** 11 | A clear and concise description of what you want to happen. 12 | 13 | **Describe alternatives you've considered** 14 | A clear and concise description of any alternative solutions or features you've considered. 15 | 16 | **Additional context** 17 | Add any other context or screenshots about the feature request here. 18 | -------------------------------------------------------------------------------- /docs/api_reference/input/read_nc_moist.md: -------------------------------------------------------------------------------- 1 | # mooda.read_nc_moist(path, resample_rule=False) 2 | 3 | ## Reference 4 | 5 | Open a NetCDF file from [MOIST](http://www.moist.it/sites/western_ionian_sea/2). 6 | This method only works with the files generated from CTDs. 7 | 8 | ### Parameters 9 | 10 | * path: Path of the NetCDF file. (str) 11 | * resample_rule: Time resample method. Use resample_rule = False to do not resample. See DateOffset objects [here](https://pandas.pydata.org/pandas-docs/stable/user_guide/timeseries.html). (str) 12 | 13 | ### Returns 14 | 15 | * wf: WaterFrame 16 | 17 | Return to [API reference](../index_api_reference.md) 18 | -------------------------------------------------------------------------------- /mooda/waterframe/output/to_pkl.py: -------------------------------------------------------------------------------- 1 | """ Implementation of WaterFrame.to_pkl(path) """ 2 | import pickle 3 | 4 | 5 | def to_pkl(self, path_pkl=None): 6 | """ 7 | Save the WaterFrame into a pickle file. 8 | 9 | Parameters 10 | ---------- 11 | path_pkl: str 12 | Location of the pickle file. If path_pkl is None, the path will be the metadata['id']. 13 | 14 | Returns 15 | ------- 16 | path_pkl: str 17 | Location of the pickle file. 18 | """ 19 | if path_pkl is None: 20 | path_pkl = self.metadata['id'] + '.pkl' 21 | 22 | pickle.dump(self.__dict__, open(path_pkl, "wb")) 23 | return path_pkl 24 | -------------------------------------------------------------------------------- /mooda/input/read_pkl.py: -------------------------------------------------------------------------------- 1 | """ Implementation of mooda.read_pkl(path) """ 2 | import pickle 3 | from .. import WaterFrame 4 | 5 | 6 | def read_pkl(path_pkl): 7 | """ 8 | Get a WaterFrame from a pickle file. 9 | 10 | Parameters 11 | ---------- 12 | path_pkl: str 13 | Location of the pickle file. 14 | 15 | Returns 16 | ------- 17 | wf_pkl: WaterFrame 18 | """ 19 | wf_pkl = WaterFrame() 20 | 21 | pickle_dataset = pickle.load(open(path_pkl, "rb")) 22 | 23 | wf_pkl.data = pickle_dataset.get('data') 24 | wf_pkl.vocabulary = pickle_dataset.get('vocabulary') 25 | wf_pkl.metadata = pickle_dataset.get('metadata') 26 | 27 | return wf_pkl 28 | -------------------------------------------------------------------------------- /docs/api_reference/waterframe/analysis/reduce_memory.md: -------------------------------------------------------------------------------- 1 | # WaterFrame.reduce_memory(*inplace*=*True*) 2 | 3 | ## Reference 4 | 5 | Data in a WaterFrame is saved in a pandas DataFrame. By default, the obtained dataset can be very heavy in memory because column types of the pandas DataFrame are defined to accept heavy value types. This method redefine the column types ad typically reduced the dataset size in memory by 30% - 50%. Ref: https://www.kaggle.com/arjanso/reducing-dataframe-memory-size-by-65 6 | 7 | ### Parameters 8 | 9 | * inplace: If false, the method will return a new WaterFrame. Otherwise, it returns True (bool) 10 | 11 | ### Returns 12 | 13 | * True or a new WaterFrame 14 | 15 | Return to [mooda.WaterFrame](../waterframe.md). 16 | -------------------------------------------------------------------------------- /mooda/waterframe/output/to_json.py: -------------------------------------------------------------------------------- 1 | """ 2 | Function to be imported in a WaterFrame. It creates a JSON with the WaterFrame information. 3 | """ 4 | import json 5 | 6 | 7 | def to_json(self): 8 | """ 9 | Get a JSON with the WaterFrame information. 10 | 11 | Returns 12 | ------- 13 | json_string: str 14 | JSON string. 15 | """ 16 | # Convert all dict values into str 17 | big_dict = { 18 | "metadata": dict(zip(self.metadata, map(str, self.metadata.values()))), 19 | "vocabulary": dict(zip(self.vocabulary, map(str, self.vocabulary.values()))), 20 | "data": self.data.to_json() 21 | } 22 | 23 | json_string = json.dumps(big_dict) 24 | 25 | return json_string 26 | -------------------------------------------------------------------------------- /docs/api_reference/util/emso/get_fig_map.md: -------------------------------------------------------------------------------- 1 | # mooda.emso.get_fig_map(*parameters*=*[]*, *platform_codes*=*[]*, *sites*=*[]*) 2 | 3 | ## Reference 4 | 5 | Get the plotly figure 'line' from the EMSO ERIC API. 6 | 7 | ### Parameters 8 | 9 | * parameters: List of accepted 'parameter' (List[str]) 10 | * platform_codes: List of accepted 'platform_code' (List[str]) 11 | * sites: List of accepted 'site' (List[str]) 12 | 13 | ### Returns 14 | 15 | * fig: Plotly figure (dict) 16 | 17 | ### Example 18 | 19 | ```python 20 | import mooda as md 21 | import plotly.io as pio 22 | 23 | emso = md.util.EMSO(user='LOGIN', password='PASSWORD') 24 | 25 | fig = emso.get_fig_map() 26 | pio.show(fig) 27 | ``` 28 | 29 | Output: 30 | 31 | ![fig_line plot](../img_util/emso_fig_map.png) 32 | 33 | Return to [Index](../../index_api_reference.md). 34 | -------------------------------------------------------------------------------- /mooda/waterframe/analysis/info_metadata.py: -------------------------------------------------------------------------------- 1 | """ Implementation of WaterFrame.info_metadata(keys=None) """ 2 | 3 | 4 | def info_metadata(self, keys=None): 5 | """ 6 | It returns a formatted string with the metadata information. 7 | 8 | Parameters 9 | ---------- 10 | keys: string or list of strings (optional) 11 | Keys of WaterFrame.metadata 12 | 13 | Returns 14 | ------- 15 | message: string 16 | Message with the metadata information. 17 | """ 18 | 19 | if keys is None: 20 | keys = self.metadata.keys() 21 | 22 | message = "" 23 | for key, value in self.metadata.items(): 24 | if key in keys and str(value).strip() != "": 25 | message += " - {}: {}\n".format(key, value) 26 | 27 | return message[:-1] 28 | -------------------------------------------------------------------------------- /docs/api_reference/waterframe/output/to_json.md: -------------------------------------------------------------------------------- 1 | # WaterFrame.to_json() 2 | 3 | ## Reference 4 | 5 | Get a JSON with the WaterFrame information. 6 | 7 | ### Returns 8 | 9 | * json_string: JSON. (str) 10 | 11 | ## Example 12 | 13 | To reproduce the example, download the NetCDF file [MO_TS_MO_OBSEA_201401.nc](http://data.emso.eu/files/emso/obsea/mo/ts/2014/MO_TS_MO_OBSEA_201401.nc) and save it in the same python script folder. 14 | 15 | ```python 16 | import mooda as md 17 | 18 | path = "MO_TS_MO_OBSEA_201401.nc" # Path to the NetCDF file 19 | 20 | wf = md.read_nc_emodnet(path) 21 | 22 | wf_json = wf.to_json() 23 | print(f'{wf_json[: 50]}...') # Print the first 50 characters of the JSON 24 | ``` 25 | 26 | Output: 27 | 28 | ```shell 29 | {"metadata": {"platform_code": "OBSEA", "platform_... 30 | ``` 31 | 32 | Return to [mooda.WaterFrame](../waterframe.md). 33 | -------------------------------------------------------------------------------- /docs/api_reference/waterframe/iplot/iplot_location.md: -------------------------------------------------------------------------------- 1 | # wf.iplot_location() 2 | 3 | ## Reference 4 | 5 | It creates a Plotly Figure with a map and a spot of the measurement location of the WaterFrame. 6 | 7 | ### Returns 8 | 9 | * figure: Dictionary of Plotly figure. (dict) 10 | 11 | ## Example 12 | 13 | To reproduce the example, download the NetCDF file [MO_TS_MO_OBSEA_201401.nc](http://data.emso.eu/files/emso/obsea/mo/ts/2014/MO_TS_MO_OBSEA_201401.nc). 14 | 15 | ```python 16 | import mooda as md 17 | import plotly.graph_objects as go 18 | 19 | path_netcdf = "MO_TS_MO_OBSEA_201401.nc" # Path of the NetCDF file 20 | 21 | wf = md.read_nc_emodnet(path_netcdf) 22 | 23 | fig = wf.iplot_location() 24 | go.Figure(fig).show() 25 | ``` 26 | 27 | Output: 28 | 29 | [OBSEA location map example](../html_waterframe/obsea-location-example.html) 30 | 31 | Return to [mooda.WaterFrame](../waterframe.md). 32 | -------------------------------------------------------------------------------- /docs/api_reference/util/md_widget/widget_emso.md: -------------------------------------------------------------------------------- 1 | # mooda.widget_emso(*wf*, *depth_range*=*[-10, 10000]*, *user*=*''*, *password*=*''*, *token*=*''*) 2 | 3 | ## Reference 4 | 5 | It makes a Jupyter notebook widget to download data from the EMSO API. 6 | 7 | ### Parameters 8 | 9 | * wf: WaterFrame 10 | * depth_range: Range of depth (List[float]) 11 | * user: User for the EMSO ERIC API (str) 12 | * password: Password for the EMSO ERIC API (str) 13 | * token: Token for the EMSO ERIC API (str) 14 | 15 | ### Returns 16 | 17 | * main_box: Jupyter notebook widget (ipwidgets.VBox) 18 | 19 | ## Example 20 | 21 | ```python 22 | import mooda as md 23 | 24 | wf = md.WaterFrame() 25 | 26 | gui = md.widget_emso(wf) 27 | gui 28 | ``` 29 | 30 | Output: 31 | 32 | ![EMSO map](../img_util/emso-map.png) 33 | ![Output emso widget](../img_util/widget-emso.png) 34 | 35 | Return to [Index](../../index_api_reference.md). 36 | -------------------------------------------------------------------------------- /docs/api_reference/util/emso/get_info_platform_code.md: -------------------------------------------------------------------------------- 1 | # mooda.emso.get_info_platform_code(*parameters*=[], *sites*=[]) 2 | 3 | ## Reference 4 | 5 | Get available platfom codes ('platform_code') of the EMSO ERIC API. 6 | 7 | ### Parameters 8 | 9 | * parameters: List of 'parameter' (List[str]) 10 | * sites: List of site (List[str]) 11 | 12 | ### Returns 13 | 14 | * platform_codes: List of 'platform_code' (List[str]) 15 | 16 | ### Example 17 | 18 | ```python 19 | import mooda as md 20 | 21 | emso = md.util.EMSO(user='LOGIN', password='PASSWORD') 22 | 23 | platform_codes = emso.get_info_platform_code() 24 | print(*platform_codes, sep='\n') 25 | ``` 26 | 27 | Output: 28 | 29 | ``` 30 | 68422 31 | ALBATROSS 32 | ANTARES 33 | ESTOC-C 34 | EUXRo01 35 | ... 36 | ... 37 | ... 38 | Marmara-BPR2 39 | Marmara-BPR3 40 | OBSEA 41 | PAP-1 42 | W1M3A 43 | ``` 44 | 45 | Return to [Index](../../index_api_reference.md). 46 | -------------------------------------------------------------------------------- /mooda/waterframe/analysis/max_diff.py: -------------------------------------------------------------------------------- 1 | """ Implementation of WaterFrame.max_diff(parameter1, parameter2) """ 2 | 3 | 4 | def max_diff(self, parameter1, parameter2): 5 | """ 6 | It calculates the maximum difference between the values of two parameters. 7 | 8 | Parameters 9 | ---------- 10 | parameter1: str 11 | Key name of column 1 to calculate the difference. 12 | parameter2: str 13 | Key name of column 2 to calculate the difference. 14 | 15 | Returns 16 | ------- 17 | where: index 18 | The position (index) of WaterFrame.data. 19 | value: float 20 | Value of the maximum difference. 21 | """ 22 | 23 | where = (self.data[parameter1] - self.data[parameter2]).abs().idxmax() 24 | value = (self.data[parameter1] - self.data[parameter2]).abs().max() 25 | 26 | return (where, value) 27 | -------------------------------------------------------------------------------- /mooda/waterframe/iplot/iplot_correlation_headmap.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import pandas as pd 3 | import plotly.express as px 4 | import plotly.graph_objects as go 5 | from plotly.validators.scatter.marker import SymbolValidator 6 | from sklearn.linear_model import LinearRegression 7 | 8 | 9 | def iplot_correlation_headmap(self, parameters=[], **kwds): 10 | """ 11 | It uses plotly.express.imshow. 12 | 13 | Parameters 14 | ---------- 15 | parameter: str 16 | 17 | Returns 18 | ------- 19 | fig: plotly.graph_objects.Figure 20 | """ 21 | 22 | if parameters: 23 | 24 | _df = self.data.copy() 25 | _df.reset_index(inplace=True) 26 | data_frame = _df[parameters].copy() 27 | corr = data_frame.corr() 28 | 29 | fig = px.imshow(corr, **kwds) 30 | 31 | else: 32 | fig = px.imshow(**kwds) 33 | 34 | return fig 35 | -------------------------------------------------------------------------------- /docs/api_reference/util/emso/get_info_summary.md: -------------------------------------------------------------------------------- 1 | # mooda.emso.get_info_summary(*fields*=*[]*, *parameters*=*[]*, *platform_codes*=*[]*, *sites*=*[]*) 2 | 3 | ## Reference 4 | 5 | Get the most used fields of the metadatada archivements. 6 | 7 | ### Parameters 8 | 9 | * fields: List of fields to return (List[str]) 10 | * parameters: List of 'parameter' (List[str]) 11 | * platform_codes: List of 'platform_code' (List[str]) 12 | * sites: List of 'site' (List[str]) 13 | 14 | ### Returns 15 | 16 | * sumaries: List of metadata archivements (List[str]) 17 | 18 | ### Example 19 | 20 | ```python 21 | import mooda as md 22 | 23 | emso = md.util.EMSO(user='LOGIN', password='PASSWORD') 24 | 25 | sites = emso.get_info_site() 26 | print(*sites, sep='\n') 27 | ``` 28 | 29 | Output: 30 | 31 | ``` 32 | azores 33 | black-sea 34 | canarias 35 | hellenic 36 | ligurian 37 | obsea 38 | pap 39 | smartbay 40 | ``` 41 | 42 | Return to [Index](../../index_api_reference.md). 43 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | 5 | --- 6 | 7 | **Describe the bug** 8 | A clear and concise description of what the bug is. 9 | 10 | **To Reproduce** 11 | Steps to reproduce the behavior: 12 | 1. Go to '...' 13 | 2. Click on '....' 14 | 3. Scroll down to '....' 15 | 4. See error 16 | 17 | **Expected behavior** 18 | A clear and concise description of what you expected to happen. 19 | 20 | **Screenshots** 21 | If applicable, add screenshots to help explain your problem. 22 | 23 | **Desktop (please complete the following information):** 24 | - OS: [e.g. iOS] 25 | - Browser [e.g. chrome, safari] 26 | - Version [e.g. 22] 27 | 28 | **Smartphone (please complete the following information):** 29 | - Device: [e.g. iPhone6] 30 | - OS: [e.g. iOS8.1] 31 | - Browser [e.g. stock browser, safari] 32 | - Version [e.g. 22] 33 | 34 | **Additional context** 35 | Add any other context about the problem here. 36 | -------------------------------------------------------------------------------- /mooda/waterframe/analysis/rename.py: -------------------------------------------------------------------------------- 1 | """ Implementation of WaterFrame.rename(actual_name, new_name) """ 2 | 3 | 4 | def rename(self, actual_name, new_name, inplace=True): 5 | """ 6 | It renames a parameter. 7 | 8 | Parameters 9 | ---------- 10 | actual_name: str 11 | Actual name of a parameter. 12 | new_name: str 13 | New name of the parameter. 14 | inplace: bool 15 | If True, the rename is inplace and returns True 16 | 17 | Returns 18 | ------- 19 | new_wf: WaterFrame 20 | WaterFrame with the renamed parameters. 21 | """ 22 | 23 | new_data = self.data.rename( 24 | columns={actual_name: new_name, f'{actual_name}_QC': f'{new_name}_QC'}, 25 | inplace=inplace) 26 | 27 | if inplace: 28 | new_wf = True 29 | else: 30 | new_wf = self.copy() 31 | new_wf.data = new_data 32 | 33 | return new_wf 34 | -------------------------------------------------------------------------------- /docs/api_reference/waterframe/output/to_pkl.md: -------------------------------------------------------------------------------- 1 | # WaterFrame.to_pkl(*path*) 2 | 3 | ## Reference 4 | 5 | It saves the WaterFrame into a pickle file. 6 | 7 | ### Parameters 8 | 9 | * path: Path to save the pickle file (str). 10 | 11 | ### Returns 12 | 13 | * True: If the internal functions of this method do not raise any error, the return is always true (bool). 14 | 15 | ## Example 16 | 17 | To reproduce the example, download the NetCDF file [here](http://data.emso.eu/files/emso/obsea/mo/ts/MO_TS_MO_OBSEA.nc) and save it as `example.nc` in the same pyhon script folder. 18 | 19 | ```python 20 | import mooda as md 21 | 22 | path_netcdf = "example.nc" # Path of the NetCDF file 23 | 24 | wf = md.read_nc_emodnet(path_netcdf) 25 | 26 | # Save the wf into a pickle file 27 | wf.to_pkl("example.pkl") 28 | print("Pickle created.") 29 | ``` 30 | 31 | Output: 32 | 33 | ``` 34 | Pickle created. 35 | ``` 36 | 37 | Return to [mooda.WaterFrame](../waterframe.md). 38 | -------------------------------------------------------------------------------- /mooda/waterframe/qc/qc_syntax_test.py: -------------------------------------------------------------------------------- 1 | """ Implementation of wf.qc_syntax_test() """ 2 | 3 | def qc_syntax_test(self): 4 | """ 5 | It verifies that wf.data contains the recomentated data structure to pass 6 | the rest of the QC test. Each parameter (for example, TEMP) and each index 7 | (for example, TIME) must have a column with the flags of the values 8 | (for example, TEMP_QC and TIME_QC). 9 | 10 | Returns 11 | ------- 12 | success: bool 13 | The test has been successfully passed. 14 | """ 15 | # Get all columns and indices 16 | all_columns = list(self.data.keys()) 17 | all_columns += list(self.data.index.names) 18 | # Get only the names without _QC 19 | columns_no_qc = [column_name for column_name in all_columns if '_QC' not in column_name] 20 | 21 | success = True 22 | 23 | for column_no_qc in columns_no_qc: 24 | if f'{column_no_qc}_QC' not in all_columns: 25 | success = False 26 | 27 | return success 28 | -------------------------------------------------------------------------------- /docs/api_reference/waterframe/qc/qc_syntax_test.md: -------------------------------------------------------------------------------- 1 | # WaterFrame.qc_syntax_test() 2 | 3 | ## Reference 4 | 5 | It checks whether the object data contains all the QC columns required to pass the rest of the tests. 6 | 7 | ### Returns 8 | 9 | * success: The test has been successfully passed. (bool) 10 | 11 | ## Example 12 | 13 | To reproduce the example, download the NetCDF file [here](../../../examples/data/MO_TS_MO_OBSEA_201402.nc) and save it as `MO_TS_MO_OBSEA_201402.nc` in the same python script folder. 14 | 15 | ```python 16 | import mooda as md 17 | import matplotlib.pyplot as plt 18 | 19 | path = "MO_TS_MO_OBSEA_201402.nc" # Path to the NetCDF file 20 | 21 | wf = md.read_nc_emodnet(path) 22 | 23 | ok = wf.qc_syntax_test() 24 | 25 | if ok: 26 | print('The syntaxis of the data is correct') 27 | else: 28 | print('The syntaxis of the data is not correct') 29 | ``` 30 | 31 | Output: 32 | 33 | ``` 34 | The syntaxis of the data is correct 35 | ``` 36 | Return to [mooda.WaterFrame](../waterframe.md). 37 | -------------------------------------------------------------------------------- /docs/examples/index_examples.md: -------------------------------------------------------------------------------- 1 | # Examples 2 | 3 | ## General data 4 | 5 | * [Obtain a MD5 code for every NetCDF of a folder and make their MD5 files](md5_dyfamed.md) 6 | * [Make a WaterFrame following the OceanSites specification](wf_oceansite.md) 7 | * [Make a WaterFrame with fake data to evaluate the Quality Control Tests](fake_waterframe.md) 8 | * [Make a WaterFrame with fake data to evaluate the Quality Control Tests - Notebook edition](QARTOD-tests.ipynb) 9 | * [Applying QARTOD QC tests to Water Temperature dataset](temperature_qc_test.md) 10 | * [How to check data quality with a Widget for Jupyter Notebook](qc_widget.md) 11 | * [How to check data quality with a Widget for Jupyter Notebook - Notebook edition](qc_widget.ipynb) 12 | 13 | ## Using EMSO data 14 | 15 | * [How to calculate Absolute Salinity and Water Density](dyfamed-density.md) 16 | 17 | ## Using EMODnet data 18 | 19 | * [Comparison of seawater temperature of several observatories using EMODnet data](temp_spain_january_2019.md). 20 | 21 | Return to [index](../index_docs.md). 22 | -------------------------------------------------------------------------------- /docs/installation/installation.md: -------------------------------------------------------------------------------- 1 | # Installing mooda 2 | 3 | ## Installing from PyPI 4 | 5 | mooda can be installed via pip from PyPI. 6 | 7 | ```cmd 8 | pip install mooda 9 | ``` 10 | 11 | ## Installing from GitHub releases 12 | 13 | In Github, we release alpha and beta versions. Go to the [release folder](https://github.com/rbardaji/mooda/releases), copy the link address of the gz.tar file and then, use pip to instal mooda. 14 | 15 | Example: 16 | 17 | ```cmd 18 | pip install https://github.com/rbardaji/mooda/archive/v0.2.0-alpha1.tar.gz 19 | ``` 20 | 21 | ## Installing from source 22 | 23 | You can [download](https://github.com/rbardaji/mooda/archive/master.zip) the current github directory and install mooda via pip. 24 | 25 | ```cmd 26 | pip install 27 | ``` 28 | 29 | example: 30 | 31 | ```cmd 32 | pip install downloads/mooda-master.zip 33 | ``` 34 | 35 | or, you can open a terminal, go to the unzipped mooda folder and write: 36 | 37 | ```cmd 38 | pip install . 39 | ``` 40 | 41 | Return to the [Docs Index](../index_docs.md). 42 | -------------------------------------------------------------------------------- /docs/api_reference/waterframe/output/to_csv.md: -------------------------------------------------------------------------------- 1 | # WaterFrame.to_csv(*path*=*None*) 2 | 3 | ## Reference 4 | 5 | Create a CSV file with the WaterFrame data. 6 | The metadata and vocabulary will be placed in the first lines of the file with a # as first character of the line. 7 | 8 | ### Parameters 9 | 10 | * path: Location and filename of the csv file. If path is None, the filename will be the metadata['id']. (str) 11 | 12 | ### Returns 13 | 14 | * path: Location and filename of the csv file. 15 | 16 | ## Example 17 | 18 | To reproduce the example, download the NetCDF file [MO_TS_MO_OBSEA_201402.nc](http://data.emso.eu/files/emso/obsea/mo/ts/MO_TS_MO_OBSEA_201402.nc). 19 | 20 | ```python 21 | import mooda as md 22 | 23 | path = "MO_TS_MO_OBSEA_201402.nc" 24 | wf = md.read_nc_emodnet(path) 25 | 26 | path_csv = wf.to_csv() 27 | 28 | print(path_csv) 29 | ``` 30 | 31 | Output: 32 | 33 | ```shell 34 | MO_TS_MO_OBSEA_201402.csv 35 | ``` 36 | 37 | Note: The example makes a CSV with the name and location of the output. 38 | 39 | Return to [mooda.WaterFrame](../waterframe.md). 40 | -------------------------------------------------------------------------------- /docs/api_reference/util/emso/get_info_metadata_id.md: -------------------------------------------------------------------------------- 1 | # mooda.emso.get_info_metadata_id(*platform_codes*=[], *sites*=[]) 2 | 3 | ## Reference 4 | 5 | Get the ID of the metadata archivements of the EMSO ERIC API. 6 | 7 | ### Parameters 8 | 9 | * platform_codes: List of platform_code (List[str]) 10 | * sites: List of site (List[str]) 11 | 12 | ### Returns 13 | 14 | * metadata_ids: List of 'metadata_id' (List[str]) 15 | 16 | ### Example 17 | 18 | ```python 19 | import mooda as md 20 | 21 | emso = md.util.EMSO(user='LOGIN', password='PASSWORD') 22 | 23 | metadata_ids = emso.get_info_metadata_id() 24 | print(*metadata_ids, sep='\n') 25 | ``` 26 | 27 | Output: 28 | 29 | ``` 30 | OS_PAP-1_200905201807_D 31 | OS_Galway-coastal-buoy_201510201902_D 32 | OS_EXIF0001_201009202004_D 33 | OS_EXIF0002_201009202002_D 34 | OS_W1M3A_200406201806_D 35 | ... 36 | ... 37 | ... 38 | OS_68422_200711202004_D 39 | OS_Marmara-BPR3_201905_TS 40 | OS_Marmara-BPR2_201811201905_D 41 | OS_Marmara-BPR1_201801201808_D 42 | OS_ALBATROSS_201907202011_D 43 | ``` 44 | 45 | Return to [Index](../../index_api_reference.md). 46 | -------------------------------------------------------------------------------- /mooda/waterframe/analysis/min.py: -------------------------------------------------------------------------------- 1 | """ Implementation of WaterFrame.min(parameter_name) """ 2 | import numpy as np 3 | 4 | def min(self, parameter_min): 5 | """ 6 | It returns the minimum value of a parameter and the value's indexes. 7 | 8 | Parameters 9 | ---------- 10 | parameter_min: str 11 | Name of the parameter. 12 | 13 | Returns 14 | ------- 15 | min_dict: dict 16 | Dictionary with the following format: 17 | { 18 | '': , 19 | '': , 20 | 'name of parameter': < min value of parameter> 21 | } 22 | If min_dict is None, all the values of the parameter are NaN. 23 | """ 24 | 25 | df = self.data[parameter_min] 26 | df = df.reset_index() 27 | 28 | try: 29 | min_dict = df.loc[df[parameter_min] == df[parameter_min].min(skipna=True)].to_dict('records')[0] 30 | except IndexError: 31 | min_dict = None 32 | 33 | return min_dict 34 | -------------------------------------------------------------------------------- /mooda/input/read_json.py: -------------------------------------------------------------------------------- 1 | """ Implementation of a function to get a WaterFrame object from a JSON. """ 2 | import json 3 | import pandas as pd 4 | 5 | 6 | def read_json(self, json_string): 7 | """ 8 | It gets a WaterFrame object from a JSON. 9 | 10 | Parameters 11 | ---------- 12 | json_string: str 13 | String that contains a JSON. 14 | 15 | Returns 16 | ------- 17 | done: bool 18 | True if the operation is successful. 19 | """ 20 | 21 | done = False 22 | try: 23 | big_dict = json.loads(json_string) 24 | 25 | keys = big_dict.keys() 26 | if "metadata" in keys: 27 | self.metadata = big_dict["metadata"].copy() 28 | if "vocabulary" in keys: 29 | self.meaning = big_dict["vocabulary"].copy() 30 | if "data" in keys: 31 | self.data = pd.read_json(big_dict["data"]) 32 | else: 33 | self.data = pd.read_json(big_dict) 34 | 35 | done = True 36 | except ValueError: 37 | pass 38 | return done 39 | -------------------------------------------------------------------------------- /mooda/waterframe/analysis/max.py: -------------------------------------------------------------------------------- 1 | """ Implementation of WaterFrame.max(parameter_max) """ 2 | 3 | 4 | def max(self, parameter_max): 5 | """ 6 | It returns the maximum value of a parameter and the value's indexes. 7 | 8 | Parameters 9 | ---------- 10 | parameter_max: str 11 | Name of the parameter. 12 | 13 | Returns 14 | ------- 15 | max_dict: dict 16 | Dictionary with the following format: 17 | { 18 | '': , 19 | '': , 20 | 'name of parameter': < maximum value of parameter> 21 | } 22 | If max_dict is None, all the values of the parameter are NaN. 23 | """ 24 | 25 | df = self.data[parameter_max] 26 | df = df.reset_index() 27 | 28 | try: 29 | max_dict = df.loc[ 30 | df[parameter_max] == df[parameter_max].max(skipna=True)].to_dict('records')[0] 31 | except IndexError: 32 | max_dict = None 33 | 34 | return max_dict 35 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 rbardaji 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /docs/api_reference/waterframe/plot/plot.md: -------------------------------------------------------------------------------- 1 | # WaterFrame.plot(***kwds*) 2 | 3 | ## Reference 4 | 5 | It calls the pandas DataFrame.plot() method. 6 | 7 | ### Parameters 8 | 9 | * **kwds: All other plotting keyword arguments to be passed to [DataFrame.plot()](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.plot.html#pandas.DataFrame.plot). 10 | 11 | ### Returns 12 | 13 | * ax: Axes of the plot. (matplotlib.AxesSubplot) 14 | 15 | ## Example 16 | 17 | To reproduce the example, download the NetCDF file [here](http://data.emso.eu/files/emso/obsea/mo/ts/2014/MO_TS_MO_OBSEA_201401.nc) and save it as `example.nc` in the same python script folder. 18 | 19 | ```python 20 | import mooda as md 21 | import matplotlib.pyplot as plt 22 | 23 | path = "MO_TS_MO_OBSEA_201401.nc" # Path to the NetCDF file 24 | 25 | wf = md.read_nc_emodnet(path) 26 | 27 | wf.resample('H') 28 | 29 | wf.plot(y=['TEMP', 'ATMS']) 30 | plt.tight_layout() 31 | plt.show() 32 | ``` 33 | 34 | Output: 35 | 36 | ![Plot example][plot-example] 37 | 38 | Return to [mooda.WaterFrame](../waterframe.md). 39 | 40 | [plot-example]: ../img_waterframe/plot-example.png 41 | -------------------------------------------------------------------------------- /docs/api_reference/input/read_nc.md: -------------------------------------------------------------------------------- 1 | # mooda.read_nc(*path*) 2 | 3 | ## Reference 4 | 5 | Read data form NetCDF file and create a WaterFrame. 6 | 7 | ### Parameters 8 | 9 | * path: Path of the NetCDF file (str). 10 | 11 | ### Returns 12 | 13 | * wf: WaterFrame 14 | 15 | ## Example 16 | 17 | To reproduce the example, download the NetCDF file [here](https://github.com/rbardaji/mooda/blob/14f4fd776d30a6a2e3f7bc0920996dee2b8a0cb3/docs/examples/data/TEMP.nc) and save it as `example.nc` in the same pyhon script folder. 18 | 19 | ```python 20 | import mooda as md 21 | 22 | path_netcdf = "example.nc" # Path of the NetCDF file 23 | 24 | wf = md.read_nc(path_netcdf) 25 | print(wf) 26 | ``` 27 | 28 | Output: 29 | 30 | ``` 31 | Memory usage: 2.648 MBytes 32 | Parameters: 33 | - TEMP: water temperature (degree_Celsius) 34 | - Min value: -2147483647.0 35 | - TIME: 2023-04-30 22:00:00 36 | - DEPTH: -3.0 37 | - Max value: 29.1200008392334 38 | - TIME: 2023-08-20 13:00:00 39 | - DEPTH: nan 40 | - Mean value: -120947890.73436177 41 | ``` 42 | 43 | Return to [API reference](../index_api_reference.md). 44 | -------------------------------------------------------------------------------- /mooda/waterframe/analysis/info_vocabulary.py: -------------------------------------------------------------------------------- 1 | """ Implementation of WaterFrame.info_vocabulary(keys=None) """ 2 | 3 | 4 | def info_vocabulary(self, keys=None): 5 | """ 6 | It returns a formatted string with the vocabulary information. 7 | 8 | Parameters 9 | ---------- 10 | keys: string or list of strings (optional) 11 | The return message will contain the information of the input keys. 12 | If keys is None, all keys will be added to the return message. 13 | 14 | Returns 15 | ------- 16 | message: str 17 | Message with the vocabulary information. 18 | """ 19 | 20 | if keys is None: 21 | keys = self.vocabulary.keys() 22 | 23 | message = "" 24 | for key, vocabulary_dict in self.vocabulary.items(): 25 | if key in keys: 26 | message += " - {}\n".format(key) 27 | for vocabulary_key, vocabulary_value in vocabulary_dict.items(): 28 | if str(vocabulary_value).strip() != "": 29 | message += " - {}: {}\n".format(vocabulary_key, vocabulary_value) 30 | 31 | return message[:-1] 32 | -------------------------------------------------------------------------------- /docs/api_reference/waterframe/iplot/iplot_data_intervals.md: -------------------------------------------------------------------------------- 1 | # wf.iplot_data_intervals(*resample_rule*=*'D'*, ***kwds*) 2 | 3 | ## Reference 4 | 5 | It uses plotly.express.timeline. It creates a plot to view the time intervals of the parameters. 6 | 7 | ### Parameters 8 | 9 | * resample_rule: Resample rule. (None, str) 10 | * **kwds: Arguments from plotly.express.timeline 11 | 12 | ### Returns 13 | 14 | * figure: Dictionary of Plotly figure. (dict) 15 | 16 | ## Example 17 | 18 | To reproduce the example, download the NetCDF file [MO_TS_MO_OBSEA_201401.nc](http://data.emso.eu/files/emso/obsea/mo/ts/2014/MO_TS_MO_OBSEA_201401.nc). 19 | 20 | ```python 21 | import mooda as md 22 | 23 | wf = md.read_nc_emodnet("MO_TS_MO_OBSEA_201402.nc") 24 | 25 | fig = wf.iplot_data_intervals() 26 | fig.show() 27 | 28 | ``` 29 | 30 | Output: 31 | 32 | The output of this script is an interactive graph that cannot be displayed on the GitHub environment. To get the interactive chart, download and run this script on your computer. Below you will find the chart exported to png. 33 | 34 | ![Interactive time-series plot example](../img_waterframe/data-intervals-example.png) 35 | 36 | Return to [mooda.WaterFrame](../waterframe.md). 37 | -------------------------------------------------------------------------------- /docs/api_reference/util/emso/get_info_parameter.md: -------------------------------------------------------------------------------- 1 | # mooda.emso.get_info_parameter(*platform_codes*=*[]*, *sites*=*[]*) 2 | 3 | ## Reference 4 | 5 | Get available parameters of the EMSO ERIC API. 6 | 7 | ### Parameters 8 | 9 | * platform_codes: List of platform_code (List[str]) 10 | * sites: List of site (List[str]) 11 | 12 | ### Returns 13 | 14 | * parameters: RList of 'parameter' (List[str]) 15 | 16 | ### Example 17 | 18 | ```python 19 | import mooda as md 20 | 21 | emso = md.util.EMSO(user='LOGIN', password='PASSWORD') 22 | 23 | parameters = emso.get_info_parameter() 24 | print(*parameters, sep='\n') 25 | ``` 26 | 27 | Output: 28 | 29 | ``` 30 | ALTS - Altitude [meter] 31 | ATMS - Atmospheric pressure at sea level [hPa] 32 | CNDC - Electrical conductivity [S m-1] 33 | DENS - Sea water density [kg m-3] 34 | DEWT - Dew point temperature [degrees_C] 35 | ... 36 | ... 37 | ... 38 | VTPK - Wave period at spectral peak / peak period (Tp) [s] 39 | VTZM - Period of the highest wave (Thmax) [s] 40 | VZMX - Maximum zero crossing wave height (Hmax) [m] 41 | WDIR - Wind from direction relative true north [degree] 42 | WSPD - Horizontal wind speed [m s-1] 43 | ``` 44 | 45 | Return to [Index](../../index_api_reference.md). 46 | -------------------------------------------------------------------------------- /docs/api_reference/util/iplot/iplot_location.md: -------------------------------------------------------------------------------- 1 | # mooda.iplot_location(*list_wf*) 2 | 3 | ## Reference 4 | 5 | It creates a Plotly Figure with a map and a spot of the measurement location of the input WaterFrames. 6 | 7 | ### Parameters 8 | 9 | * list_wf: List of WaterFrames to be concatenated. (List of WaterFrames) 10 | 11 | ### Returns 12 | 13 | * figure: Dictionary of Plotly figure. (dict) 14 | 15 | ## Example 16 | 17 | To reproduce the example, download the NetCDF files [MO_TS_MO_OBSEA_201401.nc](http://data.emso.eu/files/emso/obsea/mo/ts/MO_TS_MO_OBSEA_201401.nc) and [MO_TS_MO_OBSEA_201402.nc](http://data.emso.eu/files/emso/obsea/mo/ts/MO_TS_MO_OBSEA_201402.nc). 18 | 19 | ```python 20 | import mooda as md 21 | import plotly.graph_objects as go 22 | 23 | path = "MO_TS_MO_OBSEA_201401.nc" 24 | 25 | wf = md.read_nc_emodnet(path) 26 | list_wf = [wf] 27 | 28 | fig = md.iplot_location(list_wf) 29 | go.Figure(fig).show() 30 | ``` 31 | 32 | Output: 33 | 34 | ![iPlot location example][iplot-location] 35 | 36 | *Note: This image is NOT the real output. This image is the output, saved in PNG.* 37 | 38 | Return to [mooda.WaterFrame](../../index_api_reference.md). 39 | 40 | [iplot-location]: ../img_util/iplot_location_example.png 41 | -------------------------------------------------------------------------------- /docs/api_reference/waterframe/qc/qc_range_test.md: -------------------------------------------------------------------------------- 1 | # WaterFrame.qc_range_test(*parameters*=*None*, *limits*=*None*, *flag*=*4*, *inplace*=*True*) 2 | 3 | ## Reference 4 | 5 | Check if the values of a parameter are out of range. 6 | 7 | ### Parameters 8 | 9 | * parameters: Parameter to apply the test. (str, list of str) 10 | * limits: (Min value, max value) of the range of correct values. (tuple or list) 11 | * flag: Flag value to write in on the fail test values. (int) 12 | * inplace: If True, it changes the flags in place and returns True. Otherwhise it returns an other WaterFrame. (bool) 13 | 14 | ### Returns 15 | 16 | * new_wf: WaterFrame 17 | 18 | ## Example 19 | 20 | To reproduce the example, download the NetCDF file [here](http://data.emso.eu/files/emso/obsea/mo/ts/MO_TS_MO_OBSEA.nc) and save it as `example.nc` in the same python script folder. 21 | 22 | ```python 23 | import mooda as md 24 | 25 | path = "MO_TS_MO_OBSEA_201401.nc" # Path to the NetCDF file 26 | 27 | wf = md.read_nc_emodnet(path) 28 | 29 | ok = wf.qc_range_test() 30 | 31 | if ok: 32 | print("Range test applied.") 33 | ``` 34 | 35 | Output: 36 | 37 | ```shell 38 | Range test applied. 39 | ``` 40 | 41 | Return to [mooda.WaterFrame](../waterframe.md). 42 | -------------------------------------------------------------------------------- /docs/api_reference/util/es_create_indexes.md: -------------------------------------------------------------------------------- 1 | # mooda.es_create_indexes(*delete_previous_indexes*=*True*, ***kwargs*) 2 | 3 | ## Reference 4 | 5 | Creation of ElasticSearch Indexes to save a WaterFrame object. 6 | 7 | ### Parameters 8 | 9 | * data_index_name: Name of the ElasticSearch index that contains the WaterFrame.data documents. (str) 10 | * metadata_index_name: Name of the ElasticSearch index that contains the WaterFrame.metadata documents. (str) 11 | * summary_index_name: Name of the ElasticSearch index that contains the summary documentation. (str) 12 | * delete_previous_indexes: Delete previous indexes with the input names and all their documents. (bool) 13 | * **kwargs: [Elasticsearch object creation arguments](https://elasticsearch-py.readthedocs.io/en/master/index.html). 14 | 15 | ### Returns 16 | 17 | * success: If sucess is true, indexes where created. (bool) 18 | 19 | ## Example 20 | 21 | To reproduce the example, install run an ElasticSeach server on localhost:9200. 22 | 23 | ```python 24 | import mooda as md 25 | 26 | done = md.es_create_indexes() 27 | 28 | if done: 29 | print("Indexes created.") 30 | ``` 31 | 32 | Output: 33 | 34 | ```shell 35 | Indexes created. 36 | ``` 37 | 38 | Return to [Index](../index_api_reference.md). -------------------------------------------------------------------------------- /docs/api_reference/util/md_widget/widget_qc.md: -------------------------------------------------------------------------------- 1 | # mooda.widget_qc(*wf*, *parameter*, *range_test*=*[-1000, 1000]*, *spike_window*=*100*, *spike_threshold*=*3.5*, *spike_influence*=*0.5*) 2 | 3 | ## Reference 4 | 5 | It makes a Data QC Widget for Jupyter Notebook. 6 | 7 | ### Parameters 8 | 9 | * wf: WaterFrame 10 | * parameter: Parameter (str) 11 | * range_test: Limits for the range test [min value, max value] (List[float]) 12 | * spike_window: Window for the spike test (int) 13 | * spike_threshold: Float for the spike test (float) 14 | * spike_influence: Influence of the bad data on the spike test (float) 15 | 16 | ### Returns 17 | 18 | * main_box: Jupyter notebook widget (ipwidgets.VBox) 19 | 20 | ## Example 21 | 22 | To reproduce the example, download the pikle files [test_qc.pkl](https://github.com/rbardaji/mooda/blob/master/docs/examples/data/test_qc.pkl). 23 | 24 | ```python 25 | import mooda as md 26 | 27 | # Location of the dataset 28 | path = r'docs\examples\data\test_qc.pkl' 29 | # Read the dataset 30 | wf = md.read_pkl(path) 31 | 32 | gui = md.widget_qc(wf, 'TEMP', range_test=[0, 50]) 33 | gui 34 | ``` 35 | 36 | Output: 37 | 38 | ![Output qc widget](../img_util/qc_widget-widget.png) 39 | 40 | Return to [Index](../../index_api_reference.md). 41 | -------------------------------------------------------------------------------- /docs/api_reference/util/md5.md: -------------------------------------------------------------------------------- 1 | # mooda.md5(*file_path*, *save_dm5*=*True*, *md5_path*=*None*) 2 | 3 | ## Reference 4 | 5 | It generates the MD5 code of the input file. It saves the code into a file if it save_md5 is True. It saves the code into the text file of 'md5_path'. If md5_path is None, the name of the file is the same as the input file with the md5 extension. 6 | 7 | ### Parameters 8 | 9 | * file_path: Path of the file to make the MD5. (str) 10 | * save_md5: If save_md5 is True, it creates a file with the MD5. (bool) 11 | * md5_path: Path of the MD5 file. If md5_path is None, the name of the file is the same as the input file with the md5 extension. (path) 12 | 13 | ### Returns 14 | 15 | * haser: MD5 code. (str) 16 | 17 | ### Example 18 | 19 | To reproduce the example, download the NetCDF file [MO_TS_MO_OBSEA_201402.nc](http://data.emso.eu/files/emso/obsea/mo/ts/MO_TS_MO_OBSEA_201402.nc). 20 | 21 | ```python 22 | import mooda as md 23 | 24 | 25 | md5_string = md.md5("MO_TS_MO_OBSEA_201402.nc") 26 | print(md5_string) 27 | ``` 28 | 29 | Output: 30 | 31 | ```shell 32 | aff8d84c53f38e5525fd312f38d1e4cf 33 | ``` 34 | 35 | *Note: The script also makes a file called MO_TS_MO_OBSEA_201402.md5 with the MD5 code.* 36 | 37 | Return to [mooda.WaterFrame](../index_api_reference.md). 38 | -------------------------------------------------------------------------------- /mooda/waterframe/analysis/corr.py: -------------------------------------------------------------------------------- 1 | """ Implementation of WaterFrame.corr(parameter1, parameter2, method='pearson', min_periods=1) """ 2 | 3 | 4 | def corr(self, parameter1, parameter2, method='pearson', min_periods=1): 5 | """ 6 | Compute pairwise correlation of data columns of parameter1 and parameter2, excluding NA/null 7 | values. 8 | 9 | Parameters 10 | ---------- 11 | parameter1: str 12 | Key name of the column 1 to correlate. 13 | parameter2: str 14 | Key name of the column 2 to correlate. 15 | method: {‘pearson’, ‘kendall’, ‘spearman’} 16 | pearson : standard correlation coefficient 17 | kendall : Kendall Tau correlation coefficient 18 | spearman : Spearman rank correlation 19 | min_periods : int, optional 20 | Minimum number of observations required per pair of columns to 21 | have a valid result. Currently only available for pearson and 22 | spearman correlation 23 | Returns 24 | ------- 25 | correlation_number: float 26 | """ 27 | correlation_number = self.data[ 28 | parameter1].corr(self.data[parameter2], method=method, min_periods=min_periods) 29 | return correlation_number 30 | -------------------------------------------------------------------------------- /docs/api_reference/util/iplot/iplot_timeseries.md: -------------------------------------------------------------------------------- 1 | # mooda.iplot_timeseries(*list_wf*, *parameter_to_plot*) 2 | 3 | ## Reference 4 | 5 | It creates a Plotly figure with the time-series of the input parameter. 6 | 7 | ### Parameters 8 | 9 | * list_wf: List of WaterFrames to be concatenated. (List of WaterFrames) 10 | * parameter_to_plot: Parameters to plot. (str) 11 | 12 | ### Returns 13 | 14 | * figure: Dictionary of Plotly figure. (dict) 15 | 16 | ## Example 17 | 18 | To reproduce the example, download the NetCDF files [MO_TS_MO_OBSEA_201401.nc](http://data.emso.eu/files/emso/obsea/mo/ts/MO_TS_MO_OBSEA_201401.nc) and [MO_TS_MO_OBSEA_201402.nc](http://data.emso.eu/files/emso/obsea/mo/ts/MO_TS_MO_OBSEA_201402.nc). 19 | 20 | ```python 21 | import mooda as md 22 | import plotly.graph_objects as go 23 | 24 | path = "MO_TS_MO_OBSEA_201401.nc" 25 | 26 | wf = md.read_nc_emodnet(path) 27 | list_wf = [wf] 28 | 29 | fig = md.iplot_timeseries(list_wf, 'TEMP') 30 | go.Figure(fig).show() 31 | ``` 32 | 33 | Output: 34 | 35 | ![iPlot timeseries example][iplot-timeseries] 36 | 37 | *Note: This image is NOT the real output. This image is the output, saved in PNG.* 38 | 39 | Return to [mooda.WaterFrame](../../index_api_reference.md). 40 | 41 | [iplot-timeseries]: ../img_util/iplot_timeseries_example.png 42 | -------------------------------------------------------------------------------- /mooda/input/read_df.py: -------------------------------------------------------------------------------- 1 | from ..waterframe import WaterFrame 2 | 3 | def read_df(df, index_time, index_depth=None, metadata={}, vocabulary={}): 4 | """ 5 | Get a WaterFrame from a pandas DataFrame. 6 | 7 | Parameters 8 | ---------- 9 | df: Pandas.DataFrame 10 | index_time: str 11 | Column with the TIME index 12 | index_depth: str 13 | Column with the DEPTH index. If index_depth is None, DEPTH = 0 14 | metadata: dict 15 | vocabulary: dict 16 | 17 | Returns 18 | ------- 19 | wf: mooda.WaterFrame 20 | """ 21 | 22 | _df = df.copy() 23 | 24 | _df.reset_index(inplace=True) 25 | 26 | wf = WaterFrame() 27 | 28 | wf.metadata = metadata 29 | wf.vocabulary = vocabulary 30 | 31 | if index_depth is None: 32 | _df['DEPTH'] = 0 33 | 34 | _df.rename(columns={index_time: 'TIME'}, inplace=True) 35 | 36 | # Add QC columns 37 | keys = _df.keys() 38 | for key in keys: 39 | if key.endswith('_QC'): 40 | continue 41 | if f'{key}_QC' in keys: 42 | continue 43 | else: 44 | _df[f'{key}_QC'] = 0 45 | 46 | # Reindex 47 | _df.set_index(['DEPTH', 'TIME'], drop=True, inplace=True) 48 | 49 | wf.data = _df 50 | 51 | return wf 52 | -------------------------------------------------------------------------------- /docs/api_reference/waterframe/analysis/use_only.md: -------------------------------------------------------------------------------- 1 | # WaterFrame.use_only(*parameters_to_use*, *inplace*=*True*) 2 | 3 | ## Reference 4 | 5 | It deletes all parameters except the input parameters. 6 | 7 | ### Parameters 8 | 9 | * parameters_to_use: List of parameter names to keep (list or str). 10 | * inplace: If True, do operation inplace and return True (bool). 11 | 12 | ### Returns 13 | 14 | * new_qf: WaterFrame after the method is applied (WaterFrame). 15 | 16 | ## Example 17 | 18 | To reproduce the example, download the NetCDF file [here](http://data.emso.eu/files/emso/obsea/mo/ts/MO_TS_MO_OBSEA.nc) and save it as `example.nc` in the same pyhon script folder. 19 | 20 | ```python 21 | import mooda as md 22 | 23 | path_netcdf = "example.nc" # Path of the NetCDF file 24 | 25 | wf = md.read_nc_emodnet(path_netcdf) 26 | 27 | # Print parameters 28 | print(f"WaterFrame original parameters: {(', ').join(wf.parameters)}") 29 | # Delete all parameters except 'TEMP' 30 | wf2 = wf.use_only('TEMP', inplace=False) 31 | print(f"New WaterFrame parameters: {(', ').join(wf2.parameters)}") 32 | ``` 33 | 34 | Output: 35 | 36 | ``` 37 | WaterFrame original parameters: PRES, TEMP, CNDC 38 | New WaterFrame parameters: TEMP 39 | ``` 40 | 41 | Return to [mooda.WaterFrame](../waterframe.md). 42 | -------------------------------------------------------------------------------- /docs/api_reference/waterframe/analysis/rename.md: -------------------------------------------------------------------------------- 1 | # WaterFrame.rename(*actual_name*, *new_name*, *inplace*=*True*) 2 | 3 | ## Reference 4 | 5 | It renames a parameter. 6 | 7 | ### Parameters 8 | 9 | * actual_name: Actual name of a parameter. (str) 10 | * new_name: New name of the parameter. (str) 11 | * inplace: If True, the rename is in place and returns True. (bool) 12 | 13 | ### Returns 14 | 15 | * new_wf: WaterFrame with the renamed parameters. (WaterFrame) 16 | 17 | ## Example 18 | 19 | To reproduce the example, download the NetCDF file [here](http://data.emso.eu/files/emso/obsea/mo/ts/MO_TS_MO_OBSEA.nc) and save it as `example.nc` in the same python script folder. 20 | 21 | ```python 22 | import mooda as md 23 | 24 | path_netcdf = "example.nc" # Path of the NetCDF file 25 | 26 | wf = md.read_nc_emodnet(path_netcdf) 27 | 28 | print(f"WaterFrame original parameters: {(', ').join(wf.parameters)}") 29 | 30 | wf.rename(actual_name='TEMP', new_name='TEMP-OBSEA', inplace=True) 31 | 32 | print(f"WaterFrame renamed parameters: {(', ').join(wf.parameters)}") 33 | ``` 34 | 35 | Output: 36 | 37 | ```shell 38 | WaterFrame original parameters: PRES, TEMP, CNDC 39 | WaterFrame renamed parameters: PRES, TEMP-OBSEA, CNDC 40 | ``` 41 | 42 | Return to [mooda.WaterFrame](../waterframe.md). 43 | -------------------------------------------------------------------------------- /docs/api_reference/util/emso/get_info_fig_plot_argument.md: -------------------------------------------------------------------------------- 1 | # mooda.emso.get_info_fig_plot_argument(*plot*, *argument*) 2 | 3 | ## Reference 4 | 5 | Get argument information and available options. 6 | 7 | ### Parameters 8 | 9 | * plot: Figure type (str) 10 | * argument: Figure argument (str) 11 | 12 | ### Returns 13 | 14 | * argument_info: (meaning of the argumnt, list of available options) (Tuple[str, List[str]]) 15 | 16 | ### Example 17 | 18 | ```python 19 | import mooda as md 20 | 21 | emso = md.util.EMSO(user='LOGIN', password='PASSWORD') 22 | 23 | plot_list = emso.get_info_fig() 24 | for plot_type in plot_list: 25 | print(plot_type) 26 | arguments = emso.get_info_fig_plot(plot_type) 27 | for argument in arguments: 28 | argument_info = emso.get_info_fig_plot_argument(plot_type, argument) 29 | print(' -', argument, '->', argument_info[0]) 30 | for option in argument_info[1]: 31 | print(' -', option) 32 | ``` 33 | 34 | Output: 35 | 36 | ``` 37 | line 38 | - platform_code -> Available platform codes (platform_code) 39 | - 68422 40 | - ALBATROSS 41 | - ANTARES 42 | - ESTOC-C 43 | ... 44 | ... 45 | ... 46 | - WDIR 47 | - WSPD 48 | - output -> Response output 49 | - html 50 | - json 51 | ``` 52 | Return to [Index](../../index_api_reference.md). 53 | -------------------------------------------------------------------------------- /docs/api_reference/util/md_widget/widget_emso_qc.md: -------------------------------------------------------------------------------- 1 | # mooda.widget_emso_qc(*wf*, *depth_range*=*[-10, 10000]*, *range_test*=*[-1000, 1000]*, *spike_window*=*100*, *spike_threshold*=*3.5*, *spike_influence*=*0.5*, *user*=*''*, *password*=*''*, *token*=*''*) 2 | 3 | ## Reference 4 | 5 | It makes a Jupyter Notebook Widget used to download EMSO data and make data quality control tests. 6 | 7 | ### Parameters 8 | 9 | * wf: WaterFrame 10 | * depth_range: Range of depth (List[float]) 11 | * user: User for the EMSO ERIC API (str) 12 | * password: Password for the EMSO ERIC API (str) 13 | * token: Token for the EMSO ERIC API (str) 14 | * parameter: Parameter (str) 15 | * range_test: Limits for the range test [min value, max value] (List[float]) 16 | * spike_window: Window for the spike test (int) 17 | * spike_threshold: Float for the spike test (float) 18 | * spike_influence: Influence of the bad data on the spike test (float) 19 | 20 | ### Returns 21 | 22 | * main_box: Jupyter notebook widget (ipwidgets.VBox) 23 | 24 | ## Example 25 | 26 | ```python 27 | import mooda as md 28 | 29 | wf = md.WaterFrame() 30 | 31 | gui = md.widget_emso_qc(wf) 32 | gui 33 | ``` 34 | 35 | Output: 36 | 37 | ![EMSO map](../img_util/emso-map.png) 38 | ![Output emso qc widget](../img_util/widget-emso-qc.png) 39 | 40 | Return to [Index](../../index_api_reference.md). 41 | -------------------------------------------------------------------------------- /docs/api_reference/waterframe/analysis/slice_time.md: -------------------------------------------------------------------------------- 1 | # WaterFrame.slice_time(*start*=*None*, *end*=*None*, *inplace*=*True*) 2 | 3 | ## Reference 4 | 5 | Delete data outside the time interval. 6 | 7 | ### Parameters 8 | 9 | * start: Start time interval with format 'YYYYMMDDhhmmss'. (str) 10 | * end: End time interval with format 'YYYYMMDDhhmmss'. (str) 11 | * inplace: If inplace is True, changes will be applied on self.data and returns True. Otherwhise, it returs the new WaterFrame. (bool) 12 | 13 | ### Returns 14 | 15 | * new_wf: (WaterFrame) 16 | 17 | ## Example 18 | 19 | To reproduce the example, download the NetCDF file [here](http://data.emso.eu/files/emso/obsea/mo/ts/MO_TS_MO_OBSEA.nc) and save it as `example.nc` in the same python script folder. 20 | 21 | ```python 22 | import mooda as md 23 | 24 | path = "MO_TS_MO_OBSEA_201401.nc" # Path to the NetCDF file 25 | 26 | wf = md.read_nc_emodnet(path) 27 | 28 | wf.slice_time("20140120000000", "20140121000000") 29 | 30 | print(wf.data['TEMP'].head()) # Print the first five values of TEMP 31 | ``` 32 | 33 | Output: 34 | 35 | ```shell 36 | TIME 37 | 2014-01-19 13.222084 38 | 2014-01-20 13.378334 39 | 2014-01-21 13.381667 40 | 2014-01-22 13.727917 41 | 2014-01-23 NaN 42 | Freq: D, Name: TEMP, dtype: float64 43 | ``` 44 | 45 | Return to [mooda.WaterFrame](../waterframe.md). 46 | -------------------------------------------------------------------------------- /docs/api_reference/waterframe/qc/qc_flat_test.md: -------------------------------------------------------------------------------- 1 | # WaterFrame.qc_flat_test(*parameters*=*None*, *window*=*3*, *flag*=*4*, *inplace*=*True*) 2 | 3 | ## Reference 4 | 5 | It detects if there are equal consecutive values in the time series. 6 | 7 | $$Q_n = \left\lbrace \begin{array}{c} K ~if ~\frac{\sum_{t = n - w}^{n} f(d,t)}{w} = f(d,n) \\ 0~ otherwise \end{array}\right.$$ 8 | 9 | ### Parameters 10 | 11 | * parameters: Parameter to apply the test. (str, list of str) 12 | * window: Size of the moving window of values to calculate the mean. If it is 0, the function calculates the optimal window. (int) 13 | * flag: Flag value to write in on the fail test values. (int) 14 | * inplace: If True, it changes the flags in place and returns True. Otherwhise it returns an other WaterFrame. (bool) 15 | 16 | ### Returns 17 | 18 | * new_wf: WaterFrame 19 | 20 | ## Example 21 | 22 | To reproduce the example, download the NetCDF file [here](http://data.emso.eu/files/emso/obsea/mo/ts/MO_TS_MO_OBSEA.nc) and save it as `MO_TS_MO_OBSEA_201401.nc` in the same python script folder. 23 | 24 | ```python 25 | import mooda as md 26 | import matplotlib.pyplot as plt 27 | 28 | path = "MO_TS_MO_OBSEA_201401.nc" # Path to the NetCDF file 29 | 30 | wf = md.read_nc_emodnet(path) 31 | 32 | wf.qc_flat_test() 33 | ``` 34 | 35 | Return to [mooda.WaterFrame](../waterframe.md). 36 | -------------------------------------------------------------------------------- /mooda/waterframe/iplot/iplot_box.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import pandas as pd 3 | import plotly.express as px 4 | import plotly.graph_objects as go 5 | from plotly.validators.scatter.marker import SymbolValidator 6 | from sklearn.linear_model import LinearRegression 7 | 8 | 9 | def iplot_box(self, parameter="", color=None, **kwds): 10 | """ 11 | It uses plotly.express.box. 12 | 13 | Parameters 14 | ---------- 15 | parameter: str 16 | color: str 17 | Name of a column in self.data, or a pandas Series or array_like 18 | object. Values from this column or array_like are used to assign 19 | color to marks. 20 | If color == 'auto' and parameter != "", color = 'DEPTH' 21 | 22 | Returns 23 | ------- 24 | fig: plotly.graph_objects.Figure 25 | """ 26 | 27 | if parameter: 28 | if color == 'auto': 29 | color = 'DEPTH' 30 | 31 | _df = self.data.copy() 32 | _df.reset_index(inplace=True) 33 | data_frame = _df[[parameter, 'TIME', 'DEPTH']].copy() 34 | # Define x and yof box 35 | x = parameter 36 | 37 | fig = px.box(data_frame=data_frame, x=x, color=color, **kwds) 38 | 39 | else: 40 | if color == 'auto': 41 | color = None 42 | fig = px.box(**kwds) 43 | 44 | return fig 45 | -------------------------------------------------------------------------------- /docs/api_reference/waterframe/analysis/drop.md: -------------------------------------------------------------------------------- 1 | # WaterFrame.drop(*parameters*, *inplace*=*True*) 2 | 3 | ## Reference 4 | 5 | Remove input parameters from WaterFrame.data. 6 | 7 | ### Parameters 8 | 9 | * parameters: Parameters of WaterFrame.data. (str, list of str) 10 | * inplace: Drop in place and return 'True' or return a copy of the WaterFrame without the input parameters. (bool) 11 | 12 | ### Returns 13 | 14 | * new_wf: WaterFrame 15 | 16 | ## Example 17 | 18 | To reproduce the example, download the NetCDF file [MO_TS_MO_OBSEA_201401.nc](http://data.emso.eu/files/emso/obsea/mo/ts/2014/MO_TS_MO_OBSEA_201401.nc) and save it in the same python script folder. 19 | 20 | ```python 21 | import mooda as md 22 | 23 | path = "MO_TS_MO_OBSEA_201401.nc" # Path to the NetCDF file 24 | 25 | wf = md.read_nc_emodnet(path) 26 | 27 | print(f'Available parameters: {wf.parameters}') 28 | 29 | parameters_to_drop = ['TEMP', 'PSAL'] 30 | wf.drop(parameters_to_drop) 31 | 32 | print(f'Available parameters after drop {parameters_to_drop}: {wf.parameters}') 33 | ``` 34 | 35 | Output: 36 | 37 | ```shell 38 | Available parameters: ['DEPH', 'ATMS', 'CNDC', 'DRYT', 'PRES', 'PSAL', 'SVEL', 'TEMP', 'WDIR', 'WSPD'] 39 | Available parameters after drop ['TEMP', 'PSAL']: ['DEPH', 'ATMS', 'CNDC', 'DRYT', 'PRES', 'SVEL', 'WDIR', 'WSPD'] 40 | ``` 41 | 42 | Return to [mooda.WaterFrame](../waterframe.md). 43 | -------------------------------------------------------------------------------- /docs/api_reference/waterframe/analysis/time_intervals.md: -------------------------------------------------------------------------------- 1 | # WaterFrame.time_intervals(*parameter*, *frequency*) 2 | 3 | ## Reference 4 | 5 | It returns the index (TIME) of intervals between NaNs. 6 | 7 | ### Parameters 8 | 9 | * parameter: Column name of WaterFrame.data. (str) 10 | * frequency: Theorical sample frequency. (DateOffset, Timedelta or str) 11 | 12 | ### Returns 13 | 14 | * intervals: List of tuples with the start and end index (TIME) of each interval of data.. ([(str, str)]) 15 | 16 | ## Example 17 | 18 | To reproduce the example, download the NetCDF file [MO_TS_MO_OBSEA_201401.nc](http://data.emso.eu/files/emso/obsea/mo/ts/2014/MO_TS_MO_OBSEA_201401.nc) and save it in the same python script folder. 19 | 20 | ```python 21 | import mooda as md 22 | 23 | path = "MO_TS_MO_OBSEA_201401.nc" # Path to the NetCDF file 24 | 25 | wf = md.read_nc_emodnet(path) 26 | 27 | print(f'Available parameters: {wf.parameters}') 28 | 29 | parameter = 'TEMP' # Temperature 30 | 31 | print(f"Time intervals of {wf.vocabulary.get(parameter).get('long_name')} ", 32 | f"between gaps: {wf.time_intervals(parameter, 'H')}") 33 | ``` 34 | 35 | Output: 36 | 37 | ```shell 38 | Data intervals of Sea temperature between gaps: [('2014-01-19 00:00:00', '2014-01-23 00:00:00'), ('2014-01-26 00:00:00', '2014-01-31 23:00:00')] 39 | ``` 40 | 41 | Return to [mooda.WaterFrame](../waterframe.md). 42 | -------------------------------------------------------------------------------- /mooda/waterframe/analysis/drop.py: -------------------------------------------------------------------------------- 1 | """ Implementation of WaterFrame.drop(parameters) """ 2 | 3 | def drop(self, parameters, inplace=True): 4 | """ 5 | Remove input parameters from WaterFrame.data. 6 | 7 | Parameters 8 | ---------- 9 | parameters: str, list of str 10 | Parameters of WaterFrame.data. 11 | inplace: bool 12 | If True, Drop in place and return 'True', If False, return a copy of the WaterFrame 13 | without the input parameters. 14 | 15 | Returns 16 | ------- 17 | new_wf: WaterFrame 18 | """ 19 | keys = [] 20 | if isinstance(parameters, str): 21 | keys.append(parameters) 22 | keys.append(parameters + '_QC') 23 | elif isinstance(keys, list): 24 | for parameter in parameters: 25 | keys.append(parameter) 26 | keys.append(parameter + '_QC') 27 | 28 | if inplace: 29 | self.data.drop(keys, axis=1, inplace=True) 30 | for key in keys: 31 | self.vocabulary.pop(key) 32 | return True 33 | else: 34 | new_wf = self.copy() 35 | new_wf.vocabulary = self.vocabulary.copy() 36 | new_wf.metadata = self.metadata.copy() 37 | new_wf.data = self.data.drop(keys, axis=1) 38 | for key in keys: 39 | new_wf.vocabulary.pop(key) 40 | 41 | return new_wf 42 | -------------------------------------------------------------------------------- /docs/api_reference/util/emso/get_info_fig_plot.md: -------------------------------------------------------------------------------- 1 | # mooda.emso.get_info_fig_plot(*plot*) 2 | 3 | ## Reference 4 | 5 | Get the available arguments for the input plot. 6 | 7 | ### Parameters 8 | 9 | * plot: Figure type (str) 10 | 11 | ### Returns 12 | 13 | * argument_list: List of available arguments (List[str]) 14 | 15 | ### Example 16 | 17 | ```python 18 | import mooda as md 19 | 20 | emso = md.util.EMSO(user='LOGIN', password='PASSWORD') 21 | 22 | plot_list = emso.get_info_fig() 23 | for plot_type in plot_list: 24 | arguments = emso.get_info_fig_plot(plot_type) 25 | print(plot_type, *arguments, sep='\n - ') 26 | ``` 27 | 28 | Output: 29 | 30 | ``` 31 | line 32 | - platform_code 33 | - parameter 34 | - metadata_id 35 | - value_qc 36 | - depth_qc 37 | - time_qc 38 | - depth_min 39 | - depth_max 40 | - start_time 41 | - end_time 42 | - size 43 | - sort 44 | - x 45 | - y 46 | - title 47 | - color 48 | - rangeslider 49 | - line_type_sequence 50 | - output 51 | data_interval 52 | - interval 53 | - platform_code 54 | - parameter 55 | - metadata_id 56 | - value_qc 57 | - depth_qc 58 | - time_qc 59 | - depth_min 60 | - depth_max 61 | - start_time 62 | - end_time 63 | - title 64 | - rangeslider 65 | - output 66 | map 67 | - platform_code 68 | - site 69 | - parameter 70 | - output 71 | ``` 72 | 73 | Return to [Index](../../index_api_reference.md). 74 | -------------------------------------------------------------------------------- /mooda/waterframe/output/to_csv.py: -------------------------------------------------------------------------------- 1 | """ Implementation fo WaterFrame.to_nc() """ 2 | 3 | 4 | def to_csv(self, path=None): 5 | """ 6 | Create a CSV file with the WaterFrame data. 7 | The metadata and vocabulary will be placed in the first lines of the file with a # as first 8 | character of the line. 9 | 10 | Parameters 11 | ---------- 12 | path: str 13 | Location and filename of the csv file. 14 | If path is None, the filename will be the 15 | metadata['id']. 16 | 17 | Returns 18 | ------- 19 | path: str 20 | Location and filename of the csv file. 21 | """ 22 | 23 | filename = path 24 | if path is None: 25 | filename = self.metadata['id'] + '.csv' 26 | 27 | with open(filename, 'w') as f: 28 | f.write('# METADATA\n') 29 | for key, value in self.metadata.items(): 30 | if value != '': 31 | f.write(f'# {key}: {value}\n') 32 | f.write('\n') 33 | f.write('# VOCABULARY\n') 34 | for key, definition in self.vocabulary.items(): 35 | f.write(f'# {key}:\n') 36 | for key_definition, value_definition in definition.items(): 37 | f.write(f'# - {key_definition}: {value_definition}\n') 38 | f.write('\n') 39 | 40 | # Save data in a csv 41 | self.data.to_csv(filename, mode='a') 42 | 43 | return filename 44 | -------------------------------------------------------------------------------- /docs/api_reference/waterframe/plot/plot_timebar.md: -------------------------------------------------------------------------------- 1 | # wf.plot_timebar(*keys*, *ax*=*None*, *time_interval_mean*=*None*) 2 | 3 | ## Reference 4 | 5 | Make a bar plot of the input keys. 6 | The bars are positioned at x with date/time. Their dimensions are given by height. 7 | 8 | ### Parameters 9 | 10 | * keys: Keys of self.data to plot. (list of str) 11 | * ax: It is used to add the plot to an input axes object. (matplotlib.axes) 12 | * time_interval_mean: It calculates an average value of a time interval. You can find all of the resample options [here](https://pandas.pydata.org/pandas-docs/stable/user_guide/timeseries.html). 13 | 14 | ### Returns 15 | 16 | * ax: Axes of the plot. (matplotlib.AxesSubplot) 17 | 18 | ## Example 19 | 20 | To reproduce the example, download the NetCDF file [here](http://data.emso.eu/files/emso/obsea/mo/ts/2014/MO_TS_MO_OBSEA_201401.nc) and save it as `example.nc` in the same python script folder. 21 | 22 | ```python 23 | import mooda as md 24 | import matplotlib.pyplot as plt 25 | 26 | path_netcdf = "example.nc" # Path of the NetCDF file 27 | 28 | wf = md.read_nc_emodnet(path_netcdf) 29 | 30 | wf.plot_timebar('TEMP', time_interval_mean='D') 31 | plt.show() 32 | ``` 33 | 34 | Output: 35 | 36 | ![Plot timebar example][plot-timebar-example] 37 | 38 | Return to [mooda.WaterFrame](../waterframe.md). 39 | 40 | [plot-timebar-example]: ../img_waterframe/plot-timebar-example.png 41 | -------------------------------------------------------------------------------- /docs/examples/emso-widget.md: -------------------------------------------------------------------------------- 1 | # How to download EMSO data with a Jupyter Notebook Widget 2 | 3 | The mooda library contains a function for downloading data through the [EMSO API](http://api.emso.eu/). The function is called [mooda.from_emso(*...*)](../api_reference/input/from_emso.md) and returns a WaterFrame object. This function can also be called via a Jupyter Notebook Widget. 4 | 5 | The widfet creates a form. In this example you want to discharge 10 water temperature values from Observatory 68422. The date period is not specified. 6 | 7 | ```python 8 | import mooda as md 9 | 10 | wf = md.WaterFrame() 11 | 12 | gui = md.widget_emso(wf) 13 | gui 14 | ``` 15 | 16 | Output: 17 | 18 | ![emso widget](img_examples/widget-emso.png) 19 | 20 | After clicking on 'Get Data': 21 | 22 | ``` 23 | Done 24 | Memory usage: 3.242 KBytes 25 | Parameters: 26 | - TEMP: Parameter without meaning 27 | - Min value: 14.017000198364258 28 | - DEPTH: 600.0 29 | - TIME: 2007-11-09 09:00:00 30 | - Max value: 20.625001907348633 31 | - DEPTH: 1.0 32 | - TIME: 2007-11-09 09:00:00 33 | - Mean value: 16.362000751495362 34 | ``` 35 | 36 | Now we have the data in the wf variable. 37 | 38 | ```python 39 | wf 40 | ``` 41 | 42 | Output: 43 | 44 | ![output 1 emso widget](img_examples/output1-emso-widget.png) 45 | ![output 2 emso widget](img_examples/output2-emso-widget.png) 46 | 47 | Return to the [Index of examples](index_examples.md). 48 | -------------------------------------------------------------------------------- /docs/api_reference/waterframe/analysis/max.md: -------------------------------------------------------------------------------- 1 | # WaterFrame.max(*parameter*) 2 | 3 | ## Reference 4 | 5 | It returns the maximum value of a parameter and the value's indexes. 6 | 7 | ### Parameters 8 | 9 | * parameter_max: Name of the parameter (str) 10 | 11 | ### Returns 12 | 13 | * max_dict: Dictionary with the following format: 14 | 15 | ```python 16 | { 17 | '': , 18 | '': , 19 | 'name of parameter': 20 | } 21 | ``` 22 | 23 | ## Example 24 | 25 | To reproduce the example, download the NetCDF file [here](http://data.emso.eu/files/emso/obsea/mo/ts/MO_TS_MO_OBSEA.nc) and save it as `example.nc` in the same python script folder. 26 | 27 | ```python 28 | import mooda as md 29 | 30 | path_netcdf = "example.nc" # Path of the NetCDF file 31 | 32 | wf = md.read_nc_emodnet(path_netcdf) 33 | min_temp = wf.min('TEMP') 34 | 35 | print(f"Minimum value of temperature: {min_temp['TEMP']}") 36 | print("At:") 37 | for key, value in min_temp.items(): 38 | if key == 'TEMP': 39 | continue 40 | else: 41 | print(f" - {key}: {value}") 42 | ``` 43 | 44 | Output: 45 | 46 | ```shell 47 | Maximum value of temperature: 21.860001038294286 48 | At: 49 | - DEPTH: 1 50 | - POSITION: 0 51 | - TIME: 2014-10-01 00:00:00 52 | ``` 53 | 54 | Return to [mooda.WaterFrame](../waterframe.md). 55 | -------------------------------------------------------------------------------- /docs/api_reference/waterframe/analysis/min.md: -------------------------------------------------------------------------------- 1 | # WaterFrame.min(*parameter*) 2 | 3 | ## Reference 4 | 5 | It returns the minimum value of a parameter and the value's indexes. 6 | 7 | ### Parameters 8 | 9 | * parameter_min: Name of the parameter (str) 10 | 11 | ### Returns 12 | 13 | * min_dict: Dictionary with the following format: 14 | ```python 15 | { 16 | '': , 17 | '': , 18 | 'name of parameter': 19 | } 20 | ``` 21 | 22 | ## Example 23 | 24 | To reproduce the example, download the NetCDF file [here](http://data.emso.eu/files/emso/obsea/mo/ts/MO_TS_MO_OBSEA.nc) and save it as `example.nc` in the same pyhon script folder. 25 | 26 | ```python 27 | import mooda as md 28 | 29 | path_netcdf = "example.nc" # Path of the NetCDF file 30 | 31 | wf = md.read_nc_emodnet(path_netcdf) 32 | min_temp = wf.min('TEMP') 33 | 34 | print(f"Minimum value of temperature: {min_temp['TEMP']}") 35 | print("At:") 36 | for key, value in min_temp.items(): 37 | if key == 'TEMP': 38 | continue 39 | else: 40 | print(f" - {key}: {value}") 41 | ``` 42 | 43 | Output: 44 | 45 | ``` 46 | Minimum value of temperature: 20.0500009523239 47 | At: 48 | - DEPTH: 1 49 | - POSITION: 0 50 | - TIME: 2014-10-30 12:00:00 51 | ``` 52 | 53 | Return to [mooda.WaterFrame](../waterframe.md). 54 | -------------------------------------------------------------------------------- /mooda/waterframe/analysis/use_only.py: -------------------------------------------------------------------------------- 1 | """ Implementation of WaterFrame.use_only(*parameters*) """ 2 | 3 | 4 | def use_only(self, parameters_to_use, inplace=True): 5 | """ 6 | It deletes all parameters except the input parameters. 7 | 8 | Parameters 9 | ---------- 10 | parameters_to_use: list of str 11 | List of parameter names. 12 | inplace: bool 13 | If True, do operation inplace and return True. 14 | 15 | Returns 16 | ------- 17 | new_wf: WaterFrame 18 | Result of the WaterFrame after the method application. 19 | """ 20 | 21 | # Force to have a list in parameters 22 | if isinstance(parameters_to_use, str): 23 | parameters_to_use = [parameters_to_use] 24 | 25 | # Check if all parameters_to_use exist 26 | parameters_qc = [] 27 | for parameter_to_use in parameters_to_use: 28 | if parameter_to_use not in self.parameters: 29 | raise KeyError(f"{parameter_to_use} is not a parameter of the WaterFrame.") 30 | else: 31 | parameters_qc.append(f"{parameter_to_use}_QC") 32 | parameters_to_use += parameters_qc 33 | 34 | if inplace: 35 | self.data = self.data[parameters_to_use] 36 | return True 37 | else: 38 | # Drop parameters and return a new WaterFrame 39 | new_wf = self.copy() 40 | new_wf.data = self.data[parameters_to_use] 41 | return new_wf 42 | -------------------------------------------------------------------------------- /mooda/waterframe/analysis/slice_time.py: -------------------------------------------------------------------------------- 1 | """ Implementation of WaterFrame.slice_time(start=None, end=None) """ 2 | import pandas as pd 3 | import datetime 4 | 5 | 6 | def slice_time(self, start=None, end=None, inplace=True): 7 | """ 8 | Delete data outside the time interval. 9 | 10 | Parameters 11 | ---------- 12 | start: str, timestamp, optional (start=None) 13 | Start time interval with format 'YYYYMMDDhhmmss' or timestamp. 14 | end: str, timestamp, optional (end=None) 15 | End time interval with format 'YYYYMMDDhhmmss' or timestamp. 16 | inplace: bool 17 | If inplace is True, changes will be applied on self.data and returns True. 18 | Otherwhise, it returs the new WaterFrame 19 | 20 | Returns 21 | ------- 22 | new_wf: WaterFrame 23 | """ 24 | start_time = None 25 | end_time = None 26 | if start: 27 | start_time = datetime.datetime.strptime(start, '%Y%m%d%H%M%S') 28 | if end: 29 | end_time = datetime.datetime.strptime(end, '%Y%m%d%H%M%S') 30 | 31 | # data = self.data.sort_index(level='TIME') 32 | data = self.data.sort_index() 33 | 34 | idx = pd.IndexSlice 35 | data = data.loc[idx[:, :, start_time:end_time], :] 36 | 37 | if inplace: 38 | self.data = data 39 | return True 40 | else: 41 | new_wf = self.copy() 42 | new_wf.data = data 43 | return new_wf 44 | -------------------------------------------------------------------------------- /docs/api_reference/input/from_emso.md: -------------------------------------------------------------------------------- 1 | # mooda.from_emso(*platform_code*, *parameters*=*[]*, *start_time*=*''*, *end_time*=*''*, *depth_min*=None, *depth_max*=None, *user*=*''*, *password*=*''*, *size*=*10*) 2 | 3 | ## Reference 4 | 5 | Get a WaterFrame with the data of the EMSO API (api.emso.eu). 6 | 7 | ### Parameters 8 | 9 | * user: Login for the EMSO ERIC API (str) 10 | * password: Password for the EMSO ERIC API (str) 11 | * platform_code: Data filtered by platform_code (str) 12 | * parameters: List of parameters to get data (List[str]) 13 | * start_time: First date of the measurement (str) 14 | * end_time: Last date of the measurement (str) 15 | * depth_min: Minimum depth of the measurement (float) 16 | * depth_max: Maximum depth of the measurement (float) 17 | * size: Number of values (int) 18 | 19 | ### Returns 20 | 21 | wf: WaterFrame 22 | 23 | ## Example 24 | 25 | ```python 26 | import mooda as md 27 | 28 | wf = md.from_emso(platform_code='ANTARES', parameters=['TEMP'], 29 | start_time='2013-01-01 00:00:00', 30 | end_time='2014-01-01 00:00:00', size=80000) 31 | 32 | print(wf) 33 | ``` 34 | 35 | Output: 36 | 37 | ``` 38 | Memory usage: 11.776 KBytes 39 | Parameters: 40 | - TEMP: Parameter without meaning 41 | - Min value: 13.232633813222249 42 | - DEPTH: 2193.0 43 | - TIME: 2013-04-20 00:00:00 44 | - Max value: 13.358148854188245 45 | - DEPTH: 2303.0 46 | - TIME: 2013-07-17 00:00:00 47 | - Mean value: 13.264398355267707 48 | ``` 49 | 50 | Return to [API reference](../index_api_reference.md). 51 | -------------------------------------------------------------------------------- /docs/api_reference/waterframe/analysis/resample.md: -------------------------------------------------------------------------------- 1 | # WaterFrame.resample(rule, method='mean', inplace=True) 2 | 3 | ## Reference 4 | 5 | Convenience method for frequency conversion and sampling of time series of the WaterFrame object. Warning: if WaterFrame.data contains MultiIndex, those indexes disappears, obtaining a single 'TIME' index. 6 | 7 | ### Parameters 8 | 9 | * rule: The offset string or object representing [target conversion](http://pandas.pydata.org/pandas-docs/stable/timeseries.html#offset-aliases) (str). 10 | * method: "mean", "max", "min". Save the new value with the mean(), max() or min() function. (str) 11 | * inplace: If True, resample in place and return 'True', If False, return a new WaterFrame. (bool) 12 | 13 | ### Returns 14 | 15 | * new_wf: WaterFrame with the renamed parameters. (WaterFrame) 16 | 17 | ## Example 18 | 19 | To reproduce the example, download the NetCDF file [here](http://data.emso.eu/files/emso/obsea/mo/ts/MO_TS_MO_OBSEA.nc) and save it as `example.nc` in the same python script folder. 20 | 21 | ```python 22 | import mooda as md 23 | 24 | path = "MO_TS_MO_OBSEA_201401.nc" # Path to the NetCDF file 25 | 26 | wf = md.read_nc_emodnet(path) 27 | 28 | wf.resample('D') 29 | print(wf.data['TEMP'].head()) # Print the first 5 values of TEMP 30 | ``` 31 | 32 | Output: 33 | 34 | ```shell 35 | TIME 36 | 2014-01-19 13.222084 37 | 2014-01-20 13.378334 38 | 2014-01-21 13.381667 39 | 2014-01-22 13.727917 40 | 2014-01-23 NaN 41 | Freq: D, Name: TEMP, dtype: float64 42 | ``` 43 | 44 | Return to [mooda.WaterFrame](../waterframe.md). 45 | -------------------------------------------------------------------------------- /docs/api_reference/util/emso/get_metadata.md: -------------------------------------------------------------------------------- 1 | # mooda.emso.get_metadata(*fields*=*[]*, *metadata_ids*=*[]*, *platform_codes*=*[]*, *sites*=*[]*) 2 | 3 | ## Reference 4 | 5 | Get all fields of the metadatada archivements. 6 | 7 | ### Parameters 8 | 9 | * fields: List of fields to return (List[str]) 10 | * metadata_ids: List of 'metadata_id' (List[str]) 11 | * parameters: List of 'prameter' (List[str]) 12 | * platform_codes: List of 'platform_code' (List[str]) 13 | * sites: List of 'site' (List[str]) 14 | 15 | ### Returns 16 | 17 | * metadatas: List of metadata archivements (List[dict]) 18 | 19 | ### Example 20 | 21 | ```python 22 | import mooda as md 23 | import pprint # For nice printing 24 | 25 | emso = md.util.EMSO(user='LOGIN', password='PASSWORD') 26 | 27 | metadatas = emso.get_metadata() 28 | for metadata in metadatas: 29 | pprint.pprint(metadata) 30 | ``` 31 | 32 | Output: 33 | 34 | ``` 35 | {'Conventions': 'CF-1.6 OceanSITES-Manual-1.2 Copernicus-InSituTAC-SRD-1.4 ' 36 | 'Copernicus-InSituTAC-ParametersList-3.1.0', 37 | 'area': 'Global Ocean', 38 | 'author': 'Coriolis and Copernicus data provider, UTM (CSIC)', 39 | 'cdm_data_type': 'Time-series', 40 | ... 41 | ... 42 | ... 43 | 'de mesures provenant de capteurs sur une ligne instrumentee', 44 | 'testOutOfDate': 'now-1day', 45 | 'time_coverage_end': '2020-11-09T23:31:12Z', 46 | 'time_coverage_start': '2019-07-20T12:29:58Z', 47 | 'title': 'EMSO Ligure Ouest : ALBATROSS capteur MICROCAT (NetCDF files)'} 48 | ``` 49 | 50 | Return to [Index](../../index_api_reference.md). 51 | -------------------------------------------------------------------------------- /docs/code_structure/rbardaji_mooda_docs.md: -------------------------------------------------------------------------------- 1 | # rbardaji/mooda/docs 2 | 3 | In this folder are the MarkDown files that make up the Project documentation. 4 | 5 | The 'docs' folder and each subfolder contain an index that helps the user move between documentation. 6 | 7 | Subfolders bring together MarkDown files with the documentation for a specific topic. For example, the 'examples' subfolder contains all the documentation for mooda examples and tutorials, and the 'api_reference' subfolder contains an explanation of mooda's capabilities. 8 | 9 | The MarkDown files that are located inside 'api_reference' and explain a specific function are made with the following template: 10 | 11 | ``` 12 | # 13 | 14 | ## Reference 15 | 16 | 17 | 18 | ### Parameters 19 | 20 | * : , () 21 | * ... 22 | * : , () 23 | 24 | ### Returns 25 | 26 | * : , () 27 | 28 | ## Example 29 | 30 | 31 | 32 | ```pythom 33 | 34 | 35 | Output: 36 | 37 | 38 | 39 | Return to [](). 40 | ``` 41 | 42 | Return to the documentation of the [rbardaji/mooda](rbardaji_mooda.md) folder. 43 | -------------------------------------------------------------------------------- /docs/api_reference/util/emso/get_user_query.md: -------------------------------------------------------------------------------- 1 | # mooda.emso.get_user_query(*size*=10, *sort*='desc') 2 | 3 | ## Reference 4 | 5 | Get the queries of the user. 6 | 7 | ### Parameters 8 | 9 | * size: Number of results [def: 10, max:10000] (int) 10 | * sort: Order of the values [def: 'desc', options: 'asc', 'desc'] (str) 11 | 12 | ### Returns 13 | 14 | * query_list: List of the queries of the user (List[str]) 15 | 16 | ### Example 17 | 18 | ```python 19 | import mooda as md 20 | 21 | emso = md.util.EMSO(user='LOGIN', password='PASSWORD') 22 | 23 | query_list = emso.get_user_query() 24 | print(*query_list, sep='\n') 25 | ``` 26 | 27 | Output: 28 | ``` 29 | http://api.emso.eu/user/query?size=10&sort=desc 30 | http://api.emso.eu/user/query?size=10&sort=desc 31 | http://api.emso.eu/fig/data_interval/10d?rangeslider=false¶meter=TEMP 32 | http://api.emso.eu/data?parameter=TEMP&platform_code=ANTARES,OBSEA&depth_min=10&depth_max=100&start_time=2016-05-08%2000%3A00%3A00&end_time=2020-06-09%2000%3A00%3A00&size=10&output=json 33 | http://api.emso.eu/info/parameter?platform_code=ANTARES,OBSEA 34 | http://api.emso.eu/info/parameter?platform_code=ANTARES 35 | http://api.emso.eu/info/platform_code 36 | http://api.emso.eu/fig/map 37 | http://api.emso.eu/data?parameter=&platform_code=&depth_min=10&depth_max=100&start_time=1970-01-01%2000%3A00%3A00&end_time=1970-01-01%2000%3A00%3A00&size=10&output=json 38 | http://api.emso.eu/data?parameter=&platform_code=&depth_min=10&depth_max=100&start_time=1970-01-01%2000%3A00%3A00&end_time=1970-01-01%2000%3A00%3A00&size=10&output=json 39 | ``` 40 | 41 | Return to [Index](../../index_api_reference.md). 42 | -------------------------------------------------------------------------------- /mooda/waterframe/iplot/iplot_data_intervals.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import plotly.express as px 3 | import plotly.graph_objects as go 4 | 5 | 6 | def iplot_data_intervals(self, resample_rule='D', **kwds): 7 | """ 8 | It uses plotly.express.timeline. 9 | It creates a plot to view the time intervals of the parameters. 10 | 11 | Parameters 12 | ---------- 13 | resample_rule: None, str 14 | Resample rule. 15 | **kwds: Arguments 16 | Arguments from plotly.express.timeline 17 | Returns 18 | ------- 19 | fig: plotly.graph_objects.Figure 20 | """ 21 | if resample_rule: 22 | _wf = self.resample(rule=resample_rule, inplace=False) 23 | else: 24 | _wf = self.copy() 25 | 26 | df_content = [] 27 | for parameter in _wf.parameters: 28 | intervals = _wf.time_intervals(parameter, resample_rule) 29 | 30 | for start, end in intervals: 31 | df_content.append( 32 | dict( 33 | Task=_wf.vocabulary[parameter].get('long_name', parameter), 34 | Start=start, 35 | Finish=end, 36 | Resource=parameter)) 37 | df = pd.DataFrame(df_content) 38 | 39 | fig = px.timeline( 40 | df, 41 | x_start="Start", 42 | x_end="Finish", 43 | y="Task", 44 | color="Resource", 45 | title='Data intervals', 46 | labels={'Task': 'Parameters'}) 47 | 48 | fig.update(layout_showlegend=False) 49 | fig.update_layout(margin=dict(l=250, r=0, t=30, b=0)) 50 | 51 | return fig 52 | -------------------------------------------------------------------------------- /docs/api_reference/waterframe/iplot/iplot_timeseries.md: -------------------------------------------------------------------------------- 1 | # wf.iplot_timeseries(*parameters_to_plot*=*None*, *mode*=*'lines'* *marker_line_width*=*0*, *marker_size*=*4*, *marker_color*=*None*, *marker_colorscale*=*'Viridis'*) 2 | 3 | ## Reference 4 | 5 | It creates a Plotly figure with the time-series of the input parameters. 6 | 7 | ### Parameters 8 | 9 | * parameters_to_plot: Parameters to plot. (str or list) 10 | * mode: Plotting points (makers), lines or lines and points (lines+markers). (str) 11 | * marker_line_width: Width of the line arround the marker. (float) 12 | * marker_size: Size of the marker. (float) 13 | * marker_color: Parameter name. Change the color of the marker related to a parameter. (str) 14 | * marker_colorscale: Color scale of markers. Options: Blackbody, Bluered, Blues,Earth, Electric, Greens, Greys, Hot, Jet, Picnic, Portland, Rainbow, RdBu, Reds, Viridis, YlGnBu, YlOrRd. (str) 15 | 16 | ### Returns 17 | 18 | * figure: Dictionary of Plotly figure. (dict) 19 | 20 | ## Example 21 | 22 | To reproduce the example, download the NetCDF file [MO_TS_MO_OBSEA_201401.nc](http://data.emso.eu/files/emso/obsea/mo/ts/2014/MO_TS_MO_OBSEA_201401.nc). 23 | 24 | ```python 25 | import mooda as md 26 | import plotly.graph_objects as go 27 | 28 | path_netcdf = "MO_TS_MO_OBSEA_201401.nc" # Path of the NetCDF file 29 | 30 | wf = md.read_nc_emodnet(path_netcdf) 31 | 32 | fig = wf.iplot_timeseries('TEMP') 33 | go.Figure(fig).show(filename='ex.html') 34 | ``` 35 | 36 | Output: 37 | 38 | [Interactive time-series plot example](../html_waterframe/iplot-timeseries-example.html) 39 | 40 | Return to [mooda.WaterFrame](../waterframe.md). 41 | -------------------------------------------------------------------------------- /docs/api_reference/waterframe/plot/plot_hist.md: -------------------------------------------------------------------------------- 1 | # WaterFrame.plot_hist(*parameters*=*None*, *mean_line*=*False*, ***kwds*) 2 | 3 | ## Reference 4 | 5 | Make a histogram of the WaterFrame's. A histogram is a representation of the distribution of data. 6 | 7 | This function calls pandas.DataFrame.hist(), on each parameter of the WaterFrame, resulting in one histogram per parameter. 8 | 9 | ### Parameters 10 | 11 | * parameters: keys of self.data to be plotted. If parameters=None, it plots all parameters. (str, list of str) 12 | * mean_line: It draws a line representing the average of the values. (bool) 13 | * **kwds: All other plotting keyword arguments to be passed to [DataFrame.hist()](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.hist.html). 14 | 15 | ### Returns 16 | 17 | * ax: Axes of the plot. (matplotlib.AxesSubplot) 18 | 19 | ## Example 20 | 21 | To reproduce the example, download the NetCDF file [here](http://data.emso.eu/files/emso/obsea/mo/ts/2014/MO_TS_MO_OBSEA_201401.nc) and save it as `example.nc` in the same python script folder. 22 | 23 | ```python 24 | import mooda as md 25 | import matplotlib.pyplot as plt 26 | 27 | path_netcdf = "example.nc" # Path of the NetCDF file 28 | 29 | wf = md.read_nc_emodnet(path_netcdf) 30 | 31 | wf.plot_hist(parameters=['TEMP', 'PSAL', 'CNDC', 'PRES'], mean_line=True) 32 | 33 | plt.tight_layout() 34 | plt.show() 35 | ``` 36 | 37 | Output: 38 | 39 | ![Plot hist example][plot-hist-example] 40 | 41 | Return to [mooda.WaterFrame](../waterframe.md). 42 | 43 | [plot-hist-example]: ../img_waterframe/plot-hist-example.png 44 | -------------------------------------------------------------------------------- /mooda/waterframe/output/metadata_to_html.py: -------------------------------------------------------------------------------- 1 | import flask 2 | import os 3 | 4 | 5 | def metadata_to_html(self, filename=None, logo_link=None, footer_text=''): 6 | """ 7 | Make a html file with the metadata information. 8 | 9 | Parameters 10 | ---------- 11 | filename: str 12 | Filename and path of the html file. If filename is None, the file will be saved in the 13 | root folder with the name of the metadata['id']. 14 | logo_link: str 15 | URL with the logo to be placed on the medatada file. 16 | footer_text: str 17 | Text to be placced on the footer of the html file. 18 | 19 | Returns 20 | ------- 21 | filename: str 22 | Name of the html file. 23 | """ 24 | # Find the path to the html templates directory 25 | dirname = os.path.dirname(__file__) 26 | template_folder = os.path.join(dirname, 'html_templates') 27 | 28 | # Look for the filename, that is equal to self.metadata['id'] 29 | # If self.metadata['id'] does not exist, filename is 'metadata.html' 30 | if filename is None: 31 | filename = self.metadata.get('id', 'metadata') + '.html' 32 | 33 | app = flask.Flask('my metadata', template_folder=template_folder) 34 | 35 | with app.app_context(): 36 | rendered = flask.render_template( 37 | 'metadata.html', 38 | logo_link=logo_link, 39 | metadata_dict=self.metadata, 40 | footer_text=footer_text 41 | ) 42 | 43 | with open(filename, 'w') as handle: 44 | handle.write(rendered) 45 | 46 | return filename 47 | -------------------------------------------------------------------------------- /mooda/waterframe/iplot/iplot_location.py: -------------------------------------------------------------------------------- 1 | """ Implementation of WaterFrame.iplot_location() """ 2 | 3 | 4 | def iplot_location(self): 5 | """ 6 | It creates a Plotly Figure with a map and a spot of the measurement location of the WaterFrame. 7 | 8 | Returns 9 | ------- 10 | figure: dict 11 | Dictionary of Plotly figure 12 | """ 13 | 14 | lat = self.metadata.get('geospatial_lat_min') 15 | lon = self.metadata.get('geospatial_lon_min') 16 | text = self.metadata.get('platform_code') 17 | # Data creation 18 | data = [ 19 | dict( 20 | type="scattergeo", 21 | lon=[lon], 22 | lat=[lat], 23 | mode='markers', 24 | marker=dict( 25 | size=16, 26 | ), 27 | text=text 28 | ) 29 | ] 30 | 31 | # Configuration of the zoom 32 | if lat is not None and lon is not None: 33 | lataxis = dict(range=[float(lat)-9, float(lat)+9]) 34 | lonaxis = dict(range=[float(lon)-16, float(lon)+16]) 35 | else: 36 | lataxis = None 37 | lonaxis = None 38 | 39 | layout = dict( 40 | geo=dict( 41 | lakecolor="rgb(255, 255, 255)", 42 | resolution=50, 43 | showcoastlines=True, 44 | showland=True, 45 | landcolor="rgb(229, 229, 229)", 46 | countrycolor="rgb(255, 255, 255)", 47 | coastlinecolor="rgb(255, 255, 255)", 48 | lataxis=lataxis, 49 | lonaxis=lonaxis 50 | ), 51 | margin=dict(l=10, r=10, t=0, b=0), 52 | ) 53 | 54 | figure = dict(data=data, layout=layout) 55 | return figure 56 | -------------------------------------------------------------------------------- /mooda/waterframe/output/to_nc.py: -------------------------------------------------------------------------------- 1 | """ Function to be imported in a WaterFrame. It save the WaterFrame into a NetCDF file. """ 2 | from xarray import Dataset 3 | 4 | 5 | def to_nc(self, path=None, nc_format="NETCDF4"): 6 | """ 7 | It saves the WaterFrame into a NetCDF. 8 | 9 | Parameters 10 | ---------- 11 | path: str 12 | Path to save the NetCDF. If path is None, the filename will be metadata['id']. 13 | nc_format: str 14 | Specify the NetCDF format (NETCDF3_64BIT, NETCDF4). 15 | 16 | Returns 17 | ------- 18 | path: str 19 | Path where the file is placed. 20 | """ 21 | 22 | if path is None: 23 | path = self.metadata['id'] + '.nc' 24 | 25 | # Sometimes the metadata contains a list of str. 26 | # It can crash the creation of the NetCDF3_64Bits. 27 | # We are going to change the list of str to str 28 | metadata_netcdf = self.metadata.copy() 29 | for key, value in metadata_netcdf.items(): 30 | if isinstance(value, list): 31 | metadata_netcdf[key] = ', '.join(value) 32 | 33 | # Multiindex is not alloud yet in to_netcdf of xarray 34 | df = self.data.reset_index() 35 | df.set_index('TIME', inplace=True) 36 | 37 | # Creation of an xarray dataset 38 | ds = Dataset(data_vars=df, attrs=metadata_netcdf) 39 | for key in self.parameters: 40 | try: 41 | ds[key].attrs = self.vocabulary[key] 42 | except KeyError: # Variable without vocabulary 43 | pass 44 | 45 | # Creation of the nc file 46 | ds.to_netcdf(path, format=nc_format) 47 | 48 | return path 49 | -------------------------------------------------------------------------------- /docs/api_reference/util/emso/get_fig_data_interval.md: -------------------------------------------------------------------------------- 1 | # mooda.emso.get_fig_data_interval(*interval*=*'D'*, *depth_max*=*None*, *depth_min*=*None*, *depth_qcs*:=*[]*, *end_time*=*''*, *metadata_ids*=*[]*, *parameters*=*[]*, *platform_codes*=*[]*, *rangeslider*=*False*, *start_time*=*''*, *time_qcs*=*[]*, *title*=*''*, *value_qcs*=*[]*) 2 | 3 | ## Reference 4 | 5 | Get the plotly figure 'Data Interval' from the EMSO ERIC API. 6 | 7 | ### Parameters 8 | 9 | * interval: Period to find a data value (str) 10 | * depth_max: Maximun depth of the measurement (int) 11 | * depth_min: Minimum depth of the measurement (int) 12 | * depth_qcs: List of QC values accepted for the depth_qc field (List[int]) 13 | * end_time: Maximum date of the measurement (str) 14 | * metadata_ids: List of accepted 'metadata_id' (List[str]) 15 | * parameters: List of accepted 'parameter' (List[str]) 16 | * platform_codes: List of accepted 'platform_code' (List[str]) 17 | * rangeslider: Enable a range slider on to bottom of the graph (bool) 18 | * start_time: Minimun date of the meassurement (str) 19 | * time_qcs: List of accepted values for the field time_qc (List[int]) 20 | * title: Title of the figure (str) 21 | * value_qcs: List of accepted values for the field of value_qc (List[int]) 22 | 23 | ### Returns 24 | 25 | * fig: Plotly figure (dict) 26 | 27 | ### Example 28 | 29 | ```python 30 | import mooda as md 31 | import plotly.io as pio 32 | 33 | emso = md.util.EMSO(user='LOGIN', password='PASSWORD') 34 | 35 | fig = emso.get_fig_data_interval(parameters=['TEMP']) 36 | pio.show(fig) 37 | ``` 38 | 39 | Output: 40 | 41 | ![data_interval plot](../img_util/emso_data_interval_TEMP.png) 42 | 43 | Return to [Index](../../index_api_reference.md). 44 | -------------------------------------------------------------------------------- /mooda/waterframe/analysis/time_intervals.py: -------------------------------------------------------------------------------- 1 | """ Implementation of WaterFrame.data_intervals(parameter) """ 2 | 3 | 4 | def time_intervals(self, parameter, frequency): 5 | """ 6 | It returns the index (TIME) of intervals between NaNs. 7 | 8 | Parameters 9 | ---------- 10 | parameter: str 11 | Column name of WaterFrame.data. 12 | frequency: DateOffset, Timedelta or str 13 | Theorical sample frequency. 14 | 15 | Returns 16 | ------- 17 | intervals: [(str, str)] 18 | List of tuples with the start and end index (TIME) of each interval of 19 | data. 20 | """ 21 | # Creation of the DataFrame with the required info 22 | df = self.data.copy() 23 | 24 | df.reset_index(inplace=True) 25 | df.set_index('TIME', inplace=True) 26 | df.sort_index(inplace=True) 27 | 28 | # print(df[parameter]['2014-01-19 00:00:00']) 29 | df = df.resample(frequency).mean() 30 | 31 | # Creation of a timeseries with the positions of null values 32 | ts = df[parameter].isnull() 33 | 34 | # Check where are the intervals 35 | intervals = [] 36 | in_interval = False 37 | end = None 38 | for index, value in ts.items(): 39 | end = index.strftime('%Y-%m-%d %H:%M:%S') 40 | if in_interval is False and value is False: 41 | in_interval = True 42 | start = index.strftime('%Y-%m-%d %H:%M:%S') 43 | elif in_interval is True and value is True: 44 | in_interval = False 45 | intervals.append((start, end)) 46 | if in_interval is True: 47 | intervals.append((start, end)) 48 | 49 | return intervals 50 | -------------------------------------------------------------------------------- /mooda/waterframe/qc/qc_flat_test.py: -------------------------------------------------------------------------------- 1 | """ Implementation of WaterFrame.qc_flat_test(parameters=None, window=2, flag=4) """ 2 | 3 | 4 | def qc_flat_test(self, parameters=None, window=3, flag=4, inplace=True): 5 | """ 6 | It detects if there are equal consecutive values in the time series. 7 | 8 | Parameters 9 | ---------- 10 | parameters: string or list of strings, optional 11 | (parameters = None) 12 | Parameter to apply the test. 13 | window: int, optional (window = 3) 14 | Size of the moving window of values to calculate the mean. 15 | If it is 0, the function calculates the optimal window. 16 | flag: int, optional (flag = 4) 17 | Flag value to write in on the fail test values. 18 | inplace: bool 19 | If True, it changes the flags in place and returns True. 20 | Otherwhise it returns an other WaterFrame. 21 | 22 | Returns 23 | ------- 24 | new_wf: WaterFrame 25 | """ 26 | if parameters is None: 27 | parameters = self.parameters 28 | elif isinstance(parameters, str): 29 | parameters = [parameters] 30 | 31 | if window == 0: 32 | window = 2 33 | 34 | df_rolling = self.data.rolling(window).std() 35 | 36 | data = self.data.copy() 37 | 38 | for parameter in parameters: 39 | if '_QC' in parameter: 40 | return False 41 | else: 42 | data.loc[df_rolling[parameter] == 0, parameter + '_QC'] = flag 43 | 44 | if inplace: 45 | self.data = data 46 | return True 47 | else: 48 | new_wf = self.copy() 49 | new_wf.data = data 50 | return new_wf 51 | -------------------------------------------------------------------------------- /mooda/util/concat.py: -------------------------------------------------------------------------------- 1 | """ Implementation of WaterFrame.concat(waterframe) """ 2 | import pandas as pd 3 | 4 | 5 | def concat(list_wf): 6 | """ 7 | The concat function does all of the heavy lifting of performing concatenation operations between 8 | a list of WaterFrames. 9 | 10 | Parameters 11 | ---------- 12 | list_wf: List of WaterFrames 13 | List of WaterFrames to be concatenated. 14 | 15 | Returns 16 | ------- 17 | wf_one: WaterFrame 18 | WaterFrame with input data, metadata, and vocabulary concatenated. 19 | """ 20 | for index, wf in enumerate(list_wf): 21 | if index == 0: 22 | wf_one = wf.copy() 23 | else: 24 | # Check if waterframes are from the same platform 25 | if wf.metadata.get('platform_name') == wf_one.metadata.get('platform_name'): 26 | 27 | # Same metadata, just change the coverage times 28 | start_wf = wf.metadata.get('time_coverage_start') 29 | end_wf = wf.metadata.get('time_coverage_end') 30 | 31 | start_wf_one = wf_one.metadata.get('time_coverage_start') 32 | end_wf_one = wf_one.metadata.get('time_coverage_end') 33 | 34 | if start_wf < start_wf_one: 35 | wf_one.metadata['time_coverage_start'] = start_wf 36 | if end_wf > end_wf_one: 37 | wf_one.metadata['time_coverage_end'] = end_wf 38 | 39 | # Concat data 40 | wf_one.data = pd.concat([wf_one.data, wf.data]) 41 | else: 42 | raise NotImplementedError("All WaterFrames must be from the same 'platform_name'") 43 | 44 | return wf_one 45 | -------------------------------------------------------------------------------- /docs/api_reference/util/emso/get_fig_line.md: -------------------------------------------------------------------------------- 1 | # mooda.emso.get_fig_line(*depth_max*=*None*, *depth_min*=*None*, *depth_qcs*=*[]*, *end_time*=*''*, *metadata_ids*=*[]*, *parameters*=*[]*, *platform_codes*=*[]*, *size*=*10*, *start_time*=*''*, *sort*=*'desc'*, *time_qcs*=*[]*, *title*=*''*, *value_qcs*=*[]*, *x*=*'time'*, *y*=*'value'*) 2 | 3 | ## Reference 4 | 5 | Get the plotly figure 'line' from the EMSO ERIC API. 6 | 7 | ### Parameters 8 | 9 | * depth_max: Maximun depth of the measurement (int) 10 | * depth_min: Minimum depth of the measurement (int) 11 | * depth_qcs: List of QC values accepted for the depth_qc field (List[int]) 12 | * end_time: Maximum date of the measurement (str) 13 | * metadata_ids: List of accepted 'metadata_id' (List[str]) 14 | * parameters: List of accepted 'parameter' (List[str]) 15 | * platform_codes: List of accepted 'platform_code' (List[str]) 16 | * size: Number of values to make the graph (int) 17 | * start_time: Minimun date of the meassurement (str) 18 | * sort: Options: 'asc' or 'desc'. Get the first or last (in time) measurements (str) 19 | * time_qcs: List of accepted values for the field time_qc (List[int]) 20 | * title: Title of the figure (str) 21 | * value_qcs: List of accepted values for the field of value_qc (List[int]) 22 | * x: Field for the x-axis (str) 23 | * y: Field for the y-axis (str) 24 | 25 | ### Returns 26 | 27 | * fig: Plotly figure (dict) 28 | 29 | ### Example 30 | 31 | ```python 32 | import mooda as md 33 | import plotly.io as pio 34 | 35 | emso = md.util.EMSO(user='LOGIN', password='PASSWORD') 36 | 37 | fig = emso.get_fig_line(parameters=['TEMP'], platform_codes=['68422'], size=100) 38 | pio.show(fig) 39 | ``` 40 | 41 | Output: 42 | 43 | ![fig_line plot](../img_util/emso_68422_TEMP_100.png) 44 | 45 | Return to [Index](../../index_api_reference.md). 46 | -------------------------------------------------------------------------------- /docs/examples/qc_widget.md: -------------------------------------------------------------------------------- 1 | # How to check data quality with a Widget for Jupyter Notebook 2 | 3 | In this example, we will first read the dataset [test_qc.pkl](https://github.com/rbardaji/mooda/blob/master/docs/examples/data/test_qc.pkl) that contains water temperature data and then use a Jupyter Notebook widget to check the quality of the data and flag the incorrect data. 4 | 5 | To run this example on your computer, you need to download the dataset. 6 | 7 | ```python 8 | import mooda as md 9 | 10 | # Location of the dataset 11 | path = r'docs\examples\data\test_qc.pkl' 12 | # Read the dataset 13 | wf = md.read_pkl(path) 14 | 15 | wf 16 | ``` 17 | 18 | ![Output wf](img_examples/qc_widget-output_wf.png) 19 | 20 | Open the widget, loading the WaterFrame with the parameter TEMP (Water Temperature) 21 | 22 | Then, check all test (click on 'Do it!') with the following configuration: 23 | 24 | * Flat test -> Window: 2 25 | * Range test -> Limits: 1.5, 40 26 | * Spike test -> Window: 100 27 | * Spike test -> Threshold: 3.5 28 | * Spike test -> Influence: 0.5 29 | 30 | Finally, click on 'Run Tests'. The execution of the tests take a while. At the end of each test, the widget shows a graph with the result. 31 | 32 | The graphics are interactive. To view the bad data, click the option in the graph legend. 33 | 34 | ```python 35 | gui = md.widget_qc(wf, 'TEMP', range_test=[0, 50]) 36 | gui 37 | ``` 38 | 39 | ![QC Widget](img_examples/qc_widget-widget.png) 40 | 41 | ![Run test Plot 1](img_examples/qc_widget-plot1.png) 42 | 43 | ![Run test Plot 2](img_examples/qc_widget-plot1.png) 44 | 45 | ![Run test Plot 3](img_examples/qc_widget-plot1.png) 46 | 47 | ![Run test Plot 4](img_examples/qc_widget-plot1.png) 48 | 49 | ![Run test Plot 5](img_examples/qc_widget-plot5.png) 50 | 51 | Return to the [Index of examples](index_examples.md). 52 | -------------------------------------------------------------------------------- /mooda/waterframe/iplot/iplot_histogram.py: -------------------------------------------------------------------------------- 1 | import plotly.express as px 2 | 3 | 4 | def iplot_histogram(self, parameter='', nbins=None, show_median=False, **kwds): 5 | """ 6 | It uses plotly.express.histogram. 7 | Each data point is represented as a marker point, whose location is given by the x and y columns 8 | of self.data. 9 | 10 | Parameters 11 | ---------- 12 | parameter: str 13 | x axes, column or index of data. 14 | nbins: int 15 | By default, the number of bins is chosen so that this number is comparable to the 16 | typical number of samples in a bin. This number can be customized, as well as the range of values. 17 | **kwds: keywords 18 | plotly express scatter keywords. 19 | 20 | Returns 21 | ------- 22 | fig: plotly.graph_objects.Figure 23 | """ 24 | 25 | if parameter: 26 | _df = self.data.copy() 27 | _df.reset_index(inplace=True) 28 | df = _df[[parameter, 'TIME', 'DEPTH']].copy() 29 | 30 | fig = px.histogram(df, x=parameter, nbins=nbins, **kwds) 31 | 32 | if show_median: 33 | mean = df[parameter].mean() 34 | print(mean) 35 | text = dict( 36 | x=mean, y=0.95, xref='x', yref='paper', 37 | showarrow=False, xanchor='left', text=f'Mean: {mean:.3f}') 38 | shape = dict( 39 | x0=mean, 40 | x1=mean, 41 | y0=0, y1=1, 42 | xref='x', 43 | yref='paper', 44 | line_width=2) 45 | 46 | fig.update_layout( 47 | shapes=[shape], 48 | annotations=[text]) 49 | else: 50 | 51 | fig = px.histogram(dnbins=nbins, **kwds) 52 | 53 | return fig 54 | -------------------------------------------------------------------------------- /docs/examples/md5_dyfamed.md: -------------------------------------------------------------------------------- 1 | # Obtain a MD5 code for every NetCDF of a folder and make their MD5 files 2 | 3 | In this example, we have used data from the [Dyfamed observatory](https://www.seanoe.org/data/00326/43749/) with key: [70639](https://www.seanoe.org/data/00326/43749/data/70639.zip). We are going to create a MD5 file for each NetCDF file in the folder 4 | 5 | ```python 6 | import mooda as md 7 | import os 8 | 9 | # Make a list of file locations 10 | root = '/path/to/directory/' 11 | nc_files = [os.path.join(root, filename) 12 | for root, _, filenames in os.walk(root) 13 | for filename in filenames 14 | if '.nc' in filename] 15 | 16 | for nc_file in nc_files: 17 | print('Path:', nc_file) 18 | md5_code = md.md5(nc_file) 19 | print('MD5:', md5_code) 20 | ``` 21 | 22 | Output: 23 | 24 | ```shell 25 | Path: ./dyfamed/dyfamed-mooring/OS_DYFAMED_2014_D_TScurrents.nc 26 | MD5: 36d6fc606a35dda0488b7576f2b2c514 27 | Path: ./dyfamed/dyfamed-mooring/OS_DYFAMED_2006_TSOF.nc 28 | MD5: b68fe702c9ef5f9a0ff8aeaa2c40077f 29 | Path: ./dyfamed/dyfamed-mooring/OS_DYFAMED_2005_TSOF.nc 30 | MD5: a58cdb52939023d595df064109d317c2 31 | Path: ./dyfamed/dyfamed-mooring/OS_DYFAMED_2010_D_SedimentTrap.nc 32 | MD5: 0be1871ae964623347173d43f6031161 33 | Path: ./dyfamed/dyfamed-mooring/OS_DYFAMED_1996_FCO2TW.nc 34 | MD5: ad861ed36d8d305fe6ba2b03abfa4371 35 | Path: ./dyfamed/dyfamed-mooring/OS_DYFAMED_1997_FCO2TW.nc 36 | MD5: 61e412e872dcdcb51fe62d4294ddcc2e 37 | Path: ./dyfamed/dyfamed-mooring/OS_DYFAMED_2012_D_TSCTD.nc 38 | MD5: 66d9df290967290cd947cd811b8b422b 39 | Path: ./dyfamed/dyfamed-mooring/OS_DYFAMED_1998_TSOF.nc 40 | MD5: d1d237845f866175973ba55ab8e6af6b 41 | Path: ./dyfamed/dyfamed-mooring/DYF57_2017.nc 42 | MD5: 30dd80a4c4c3369e6a7c98d8ff7bc6de 43 | ... 44 | ``` 45 | 46 | Return to the [Index of examples](index_examples.md). 47 | -------------------------------------------------------------------------------- /docs/api_reference/waterframe/iplot/iplot.md: -------------------------------------------------------------------------------- 1 | # wf.iplot(*y*, *x*=*'TIME'*, *color*=*'auto'*, *plot_type*=*'scatter'*, *marginal_x*=*'histogram'*, *marginal_y*=*'box'* *trendline*=*'ols'*) 2 | 3 | ## Reference 4 | 5 | Get a figure using plotly.express. 6 | 7 | ### Parameters 8 | 9 | * y: Y axes of the plot. Column of self.data to plot. (str) 10 | * x: X axes of the plot. It can be an index or a column of self.data. (str) 11 | * color: Column of self.data, auto or None. Colors of the dots of the scatter. (str) 12 | * plot_type: Type of plot figure to make. Options: *scatter*. (str) 13 | * marginal_x: Additional graph on top x axes. Options: *None*, *rug*, *histogram*, *violin*, *box*. (str) 14 | * marginal_y: Additional graph on right y axes. Options: *None*, *rug*, *histogram*, *violin*, *box*. (str) 15 | * trendline: Activate the trendline. Options: *None*, *[ols](https://en.wikipedia.org/wiki/Ordinary_least_squares)*, *[lowess](https://en.wikipedia.org/wiki/Local_regression)*. (str) 16 | * filename: Path and name of the file to save the figure in html. (str) 17 | 18 | ### Returns 19 | 20 | * fig: Plotly figure. 21 | 22 | ## Example 23 | 24 | To reproduce the example, download the NetCDF file [MO_TS_MO_OBSEA_201402.nc](http://data.emso.eu/files/emso/obsea/mo/ts/2014/MO_TS_MO_OBSEA_201402.nc). 25 | 26 | ```python 27 | import mooda as md 28 | 29 | 30 | path_netcdf = "MO_TS_MO_OBSEA_201402.nc" # Path of the NetCDF file 31 | wf = md.read_nc_emodnet(path_netcdf) 32 | 33 | fig = wf.iplot('TEMP') 34 | fig.show() 35 | ``` 36 | 37 | Output: 38 | 39 | ![iplot example][iplot-example] 40 | 41 | *Note: The script makes an interactive charts. The image shown in this example have been generated by saving the interactive images in a PNG file.* 42 | 43 | Return to [mooda.WaterFrame](../waterframe.md). 44 | 45 | [iplot-example]: ../img_waterframe/iplot-example.png 46 | -------------------------------------------------------------------------------- /docs/api_reference/waterframe/output/metadata_to_html.md: -------------------------------------------------------------------------------- 1 | # WaterFrame.metadata_to_html(*filename*=*None*, *logo_link*=*None*, *footer_text*=*None*) 2 | 3 | ## Reference 4 | 5 | Make a html file with the metadata information. 6 | 7 | ## Parameters 8 | 9 | * filename: Filename and path of the html file. If filename is None, the file will be saved in the root folder with the name of the metadata['id']. (str) 10 | * logo_link: URL with the logo to be placed on the medatada file. (str) 11 | * footer_text: Text to be placced on the footer of the html file. (str) 12 | 13 | ## Returns 14 | 15 | * filename: Name of the html file. (str) 16 | 17 | ## Example 18 | 19 | To reproduce the example, download the NetCDF file [MO_TS_MO_OBSEA_201402.nc](http://data.emso.eu/files/emso/obsea/mo/ts/2014/MO_TS_MO_OBSEA_201402.nc) and save it in the same python script folder. 20 | 21 | ```python 22 | import mooda as md 23 | 24 | path_netcdf = 'MO_TS_MO_OBSEA_201402.nc' # Path of the NetCDF file 25 | 26 | wf = md.read_nc_emodnet(path_netcdf) 27 | 28 | logo_link = 'http://data.emso.eu/img/logo/logo-EMSO-ERIC.png' 29 | footer_text = 'Disclaimer: EMSO ERIC makes no guarantee of the quality, reliability, ' \ 30 | 'usability, availability, or suitability of any EMSO ERIC data for any particular purpose. ' \ 31 | 'Users assume all risks and liabilities, direct or indirect, associated with any use of EMSO ' \ 32 | 'ERIC data (http://emso.eu/privacy-policy/).' 33 | 34 | metadata_path = wf.metadata_to_html(logo_link=logo_link, footer_text=footer_text) 35 | print(metadata_path) 36 | ``` 37 | 38 | Output: 39 | 40 | ```shell 41 | MO_TS_MO_OBSEA_201402.html 42 | ``` 43 | 44 | Screenshot of the metadata html: 45 | 46 | ![OBSEA metadata][obsea-metadata] 47 | 48 | Return to [mooda.WaterFrame](../waterframe.md). 49 | 50 | [obsea-metadata]: ../img_waterframe/metadata-html-obsea.png 51 | -------------------------------------------------------------------------------- /mooda/util/md_widgets/widget_save.py: -------------------------------------------------------------------------------- 1 | """ Implementation of mooda.widget_save()""" 2 | import ipywidgets as widgets 3 | 4 | 5 | def widget_save(wf): 6 | """ 7 | Make a Jupyter notebook widget that allows to save the WaterFrame to a file 8 | 9 | Parameters 10 | ---------- 11 | wf: WaterFrame 12 | 13 | Returns 14 | ------- 15 | main_box: ipwidgets.VBox 16 | Jupyter notebook widget 17 | """ 18 | # Title 19 | title_label = widgets.Label('Save as...') 20 | 21 | # Filename 22 | name_label = widgets.Label('Name:') 23 | input_name = widgets.Text() 24 | 25 | # Type 26 | type_label = widgets.Label('Type:') 27 | input_type = widgets.RadioButtons( 28 | options=['csv', 'nc', 'pkl'], value='csv', disabled=False) 29 | 30 | # Button 31 | button = widgets.Button(description='Save') 32 | out_save = widgets.Output() 33 | def on_button_clicked(_): 34 | with out_save: 35 | if input_name.value: 36 | if input_type.value == 'csv': 37 | wf.to_csv(path=f'{input_name.value}.csv') 38 | elif input_type.value == 'nc': 39 | wf.to_nc(path=f'{input_name.value}.nc') 40 | elif input_type.value == 'pkl': 41 | wf.to_pkl(path_pkl=f'{input_name.value}.pkl') 42 | print('Done.') 43 | else: 44 | print('Please, write a name.') 45 | # linking button and function together using a button's method 46 | button.on_click(on_button_clicked) 47 | 48 | filename_box = widgets.HBox([name_label, input_name]) 49 | type_box = widgets.HBox([type_label, input_type]) 50 | 51 | main_box = widgets.VBox([title_label, filename_box, type_box, button, 52 | out_save]) 53 | 54 | return main_box 55 | -------------------------------------------------------------------------------- /mooda/util/md5.py: -------------------------------------------------------------------------------- 1 | """ Implementation of md.md5 """ 2 | import hashlib 3 | 4 | 5 | def md5(file_path, save_md5=True, md5_path=None): 6 | """ 7 | It generates the MD5 code of the input file. 8 | It saves the code into a file if it save_md5 is True. 9 | It saves the code into the text file of 'md5_path'. 10 | If md5_path is None, the name of the file is the same as the input file 11 | with the md5 extension. 12 | 13 | Parameters 14 | ---------- 15 | file_path: str 16 | Path of the file to make the MD5. 17 | save_md5: bool 18 | If save_md5 is True, it creates a file with the MD5. 19 | md5_path: path 20 | Path of the MD5 file. If md5_path is None, the name of the file is 21 | the same as the input file with the md5 extension. 22 | 23 | Returns 24 | ------- 25 | haser: str 26 | MD5 code. 27 | """ 28 | 29 | # Make the MD5 code 30 | haser = hashlib.md5() 31 | with open(file_path, 'rb') as open_file: 32 | content = open_file.read() 33 | haser.update(content) 34 | 35 | if save_md5: 36 | if md5_path: 37 | filename_md5 = md5_path 38 | else: 39 | # Get the same path but with md5 extension 40 | parts = file_path.split('.') 41 | filename_md5 = "" 42 | for part in parts[:-1]: 43 | filename_md5 += part 44 | filename_md5 += '.' 45 | # write the _ 46 | filename_md5 = filename_md5[:-1] + '_' 47 | filename_md5 += parts[-1] 48 | 49 | filename_md5 += ".md5" 50 | 51 | # Save the md5 code into the file 52 | with open(filename_md5, 'w') as open_file: 53 | open_file.write(haser.hexdigest()) 54 | 55 | return haser.hexdigest() 56 | -------------------------------------------------------------------------------- /mooda/util/iplot/iplot_location.py: -------------------------------------------------------------------------------- 1 | """ Implementation of mooda.iplot_location() """ 2 | 3 | 4 | def iplot_location(list_wf): 5 | """ 6 | It creates a Plotly Figure with a map and a spot of the measurement location of the input 7 | WaterFrames. 8 | 9 | Parameters 10 | ---------- 11 | list_wf: List of WaterFrames 12 | List of WaterFrames to be concatenated. 13 | 14 | Returns 15 | ------- 16 | figure: dict 17 | Dictionary of Plotly figure 18 | """ 19 | 20 | lat = [float(wf.metadata.get('geospatial_lat_min')) for wf in list_wf] 21 | lon = [float(wf.metadata.get('geospatial_lon_min')) for wf in list_wf] 22 | text = [wf.metadata.get('platform_code') for wf in list_wf] 23 | # Data creation 24 | data = [ 25 | dict( 26 | type="scattergeo", 27 | lon=lon, 28 | lat=lat, 29 | mode='markers', 30 | marker=dict( 31 | size=16, 32 | ), 33 | text=text 34 | ) 35 | ] 36 | 37 | # Configuration of the zoom 38 | if lat is not None and lon is not None: 39 | lataxis = dict(range=[min(lat)-9, max(lat)+9]) 40 | lonaxis = dict(range=[min(lon)-16, max(lon)+16]) 41 | else: 42 | lataxis = None 43 | lonaxis = None 44 | 45 | layout = dict( 46 | geo=dict( 47 | lakecolor="rgb(255, 255, 255)", 48 | resolution=50, 49 | showcoastlines=True, 50 | showland=True, 51 | landcolor="rgb(229, 229, 229)", 52 | countrycolor="rgb(255, 255, 255)", 53 | coastlinecolor="rgb(255, 255, 255)", 54 | lataxis=lataxis, 55 | lonaxis=lonaxis 56 | ), 57 | margin=dict(l=10, r=10, t=0, b=0), 58 | ) 59 | 60 | figure = dict(data=data, layout=layout) 61 | return figure 62 | -------------------------------------------------------------------------------- /docs/examples/emso-widget.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "metadata": { 3 | "language_info": { 4 | "codemirror_mode": { 5 | "name": "ipython", 6 | "version": 3 7 | }, 8 | "file_extension": ".py", 9 | "mimetype": "text/x-python", 10 | "name": "python", 11 | "nbconvert_exporter": "python", 12 | "pygments_lexer": "ipython3", 13 | "version": "3.8.4-final" 14 | }, 15 | "orig_nbformat": 2, 16 | "kernelspec": { 17 | "name": "python3", 18 | "display_name": "Python 3", 19 | "language": "python" 20 | } 21 | }, 22 | "nbformat": 4, 23 | "nbformat_minor": 2, 24 | "cells": [ 25 | { 26 | "source": [ 27 | "# How to download EMSO data with a Jupyter Notebook Widget\n", 28 | "\n", 29 | "The mooda library contains a function for downloading data through the [EMSO API](http://api.emso.eu/). The function is called [mooda.from_emso(*...*)](https://rbardaji.github.io/mooda/docs/api_reference/input/from_emso.html) and returns a WaterFrame object. This function can also be called via a Jupyter Notebook Widget.\n", 30 | "\n", 31 | "The widfet creates a form. In this example you want to discharge 10 water temperature values from Observatory 68422. The date period is not specified." 32 | ], 33 | "cell_type": "markdown", 34 | "metadata": {} 35 | }, 36 | { 37 | "cell_type": "code", 38 | "execution_count": null, 39 | "metadata": {}, 40 | "outputs": [], 41 | "source": [ 42 | "import mooda as md\n", 43 | "\n", 44 | "wf = md.WaterFrame()\n", 45 | "\n", 46 | "gui = md.widget_emso(wf)\n", 47 | "gui" 48 | ] 49 | }, 50 | { 51 | "source": [ 52 | "Now we have the data in the wf variable." 53 | ], 54 | "cell_type": "markdown", 55 | "metadata": {} 56 | }, 57 | { 58 | "cell_type": "code", 59 | "execution_count": null, 60 | "metadata": {}, 61 | "outputs": [], 62 | "source": [ 63 | "wf" 64 | ] 65 | } 66 | ] 67 | } -------------------------------------------------------------------------------- /docs/code_structure/rbardaji_mooda.md: -------------------------------------------------------------------------------- 1 | # Directory: rbardaji/mooda 2 | 3 | * **.github**: This folder hosts files that are used by the GitHub platform itself. In our case, this folder only contains the form templates to report bugs or request new functionalities, but in other repositories, this folder may contain more files. 4 | * [**docs**](rbardaji_mooda_docs.md): This folder contains the Markdown files for mooda documentation. 5 | * [**mooda**](rbardaji_mooda_mooda.md): This is the most important folder in the repository and contains the code for the mooda library. 6 | * .gitignore: A gitignore file specifies intentionally untracked files that Git should ignore. Files already tracked by Git are not affected. 7 | * LICENSE: File to define all license details. We use the MIT license. 8 | * MANIFEST.in: Code that allows to include files in source distributions. When building a source distribution for the package by default, only a minimal set of files are included. We want to include extra files in the source distribution, such as the requirements file (requirements.txt), that the setup file (setup.py) need to instal all dependencies of the package. [more info](https://packaging.python.org/guides/using-manifest-in/). 9 | * README.md: This Markdown documentation file is shown as "home" documentation/page of the GitHub repository and the GitHub page environment. 10 | * _config.yml: GitHub Pages are public webpages hosted and easily published through GitHub. The quickest way to get up and running is by using the Jekyll Theme Chooser to load a pre-made theme. This file contains the settings required to generate a GitHub-pages. 11 | * requirements.txt: List of python packages required to run mooda successfully. 12 | * setup.py: The setup.py file contains information about mooda that PyPi needs to publish install the package, like its name, a description, the requeriments, the current version etc. 13 | 14 | Return to [index](../index_docs.md). 15 | -------------------------------------------------------------------------------- /docs/api_reference/waterframe/analysis/corr.md: -------------------------------------------------------------------------------- 1 | # WaterFrame.corr(*parameter1*, *parameter2*, *method*=*'pearson'*, *min_periods*=*1*) 2 | 3 | ## Reference 4 | 5 | Compute pairwise correlation of data columns of parameter1 and parameter2, excluding NA/null values. 6 | 7 | ### Parameters 8 | 9 | * parameter1: Column name of *WaterFrame*.*data* to correlate. (str) 10 | * parameter2: Column name of *WaterFrame*.*data* to correlate. (str) 11 | * method: 'pearson', 'kendall' or 'spearman'. (str) 12 | * pearson: standard correlation coefficient 13 | * kendall: Kendall Tau correlation coefficient 14 | * spearman: Spearman rank correlation 15 | * min_periods: Minimum number of observations required per pair of columns to have a valid result. Currently only available for Pearson and Spearman correlation. (int) 16 | 17 | ### Returns 18 | 19 | * correlation_number: float 20 | 21 | ## Example 22 | 23 | To reproduce the example, download the NetCDF file [MO_TS_MO_OBSEA_201401.nc](http://data.emso.eu/files/emso/obsea/mo/ts/2014/MO_TS_MO_OBSEA_201401.nc) and save it in the same python script folder. 24 | 25 | ```python 26 | import mooda as md 27 | 28 | path = "MO_TS_MO_OBSEA_201401.nc" # Path to the NetCDF file 29 | 30 | wf = md.read_nc_emodnet(path) 31 | 32 | print(f'Available parameters: {list(wf.parameters)}') 33 | 34 | parameter1 = 'TEMP' # Temperature 35 | parameter2 = 'CNDC' # Conductivity 36 | 37 | print('Correlation factor between ', 38 | f"{wf.vocabulary.get(parameter1).get('long_name')} and ", 39 | f"{wf.vocabulary.get(parameter2).get('long_name')}: ", 40 | f"{wf.corr(parameter1, parameter2)}") 41 | ``` 42 | 43 | Output: 44 | 45 | ```shell 46 | Available parameters: ['DEPH', 'ATMS', 'CNDC', 'DRYT', 'PRES', 'PSAL', 'SVEL', 'TEMP', 'WDIR', 'WSPD'] 47 | Correlation factor between Sea temperature and Electrical conductivity: 0.9745679306570474 48 | ``` 49 | 50 | Return to [mooda.WaterFrame](../waterframe.md). 51 | -------------------------------------------------------------------------------- /docs/api_reference/util/concat.md: -------------------------------------------------------------------------------- 1 | # mooda.concat(*list_wf*) 2 | 3 | ## Reference 4 | 5 | The concat function does all of the heavy lifting of performing concatenation operations between a list of WaterFrames. 6 | 7 | ### Parameters 8 | 9 | * list_wf: List of WaterFrames to be concatenated. (List of WaterFrames) 10 | 11 | ### Returns 12 | 13 | * wf_one: WaterFrame with input data, metadata, and vocabulary concatenated. (WaterFrame) 14 | 15 | ## Example 16 | 17 | To reproduce the example, download the NetCDF files [MO_TS_MO_OBSEA_201401.nc](http://data.emso.eu/files/emso/obsea/mo/ts/MO_TS_MO_OBSEA_201401.nc) and [MO_TS_MO_OBSEA_201402.nc](http://data.emso.eu/files/emso/obsea/mo/ts/MO_TS_MO_OBSEA_201402.nc). 18 | 19 | ```python 20 | import mooda as md 21 | 22 | path_obsea_january = "MO_TS_MO_OBSEA_201401.nc" 23 | path_obsea_february = "MO_TS_MO_OBSEA_201402.nc" 24 | 25 | wf_january = md.read_nc_emodnet(path_obsea_january) 26 | wf_february = md.read_nc_emodnet(path_obsea_february) 27 | 28 | print('Range time from wf_january:', 29 | f"{wf_january.metadata.get('time_coverage_start')} -", 30 | f"{wf_january.metadata.get('time_coverage_end')}") 31 | print('Range time from wf_february: ', 32 | f"{wf_february.metadata.get('time_coverage_start')} -", 33 | f"{wf_february.metadata.get('time_coverage_end')}") 34 | 35 | wf_january_february = md.concat([wf_january, wf_february]) 36 | 37 | print('Range time from wf_january_february:', 38 | f"{wf_january_february.metadata.get('time_coverage_start')} -", 39 | f"{wf_january_february.metadata.get('time_coverage_end')}") 40 | ``` 41 | 42 | Output: 43 | 44 | ```shell 45 | Range time from wf_january: 2014-01-19T00:00:00Z - 2014-01-31T23:00:00Z 46 | Range time from wf_february: 2014-02-01T00:00:00Z - 2014-02-28T23:00:00Z 47 | Range time from wf_january_february: 2014-01-19T00:00:00Z - 2014-02-28T23:00:00Z 48 | ``` 49 | 50 | Return to [Index](../index_api_reference.md). 51 | -------------------------------------------------------------------------------- /docs/api_reference/waterframe/iplot/iplot_bar_polar.md: -------------------------------------------------------------------------------- 1 | # wf.iplot_bar_polar(theta, color, r='auto', template='xgridoff', color_continuous_scale='auto', **kwds) 2 | 3 | It uses plotly.express.bar_polar. 4 | 5 | In a polar bar plot, each row of 'color' is represented as a wedge mark in polar coordinates. 6 | 7 | ## Reference 8 | 9 | ### Parameters 10 | 11 | * theta: wf.data colum with the directions in degrees (str) 12 | * color: wf.data colum with the data to plot with colors (str) 13 | * r: wf.data column with the data to use as a radius (str) 14 | * If r = 'auto', r is the counts of 'theta' en each direction. 15 | * template: Plotly express style templates (str) 16 | * Options: 17 | * 'ggplot2' 18 | * 'seaborn' 19 | * 'simple_white' 20 | * 'plotly' 21 | * 'plotly_white' 22 | * 'plotly_dark' 23 | * 'presentation' 24 | * 'xgridoff' 25 | * 'ygridoff' 26 | * 'gridon' 27 | * 'none' 28 | * color_continuous_scale: View https://plotly.com/python/colorscales/ (plotly.express.sequential) 29 | * If color_continuous_scale = 'auto', color_continuous_scale = px.colors.sequential.Rainbow 30 | * **kwds: plotly.express.bar_polar arguments 31 | 32 | ### Returns 33 | 34 | * fig: (plotly.graph_objects.Figure) 35 | 36 | 37 | ## Example 38 | 39 | For this example we are going to download wind direction and wind speed data from EMSO platform 68422. We will download 1000 values without specifying the time range or depth. 40 | 41 | ```python 42 | import mooda as md 43 | 44 | wf = md.from_emso(platform_code='68422', parameters=['WDIR', 'WSPD'], size=1000) 45 | 46 | # Resample data hourly 47 | wf.resample('H') 48 | 49 | fig = wf.iplot_bar_polar('WDIR', 'WSPD') 50 | fig.show() 51 | ``` 52 | 53 | Output: 54 | 55 | *Note - The output graph is interactive. Below is the figure saved in a png image.* 56 | 57 | ![iplot_bar_polar](../img_waterframe/iplot_bar_polar.png) 58 | 59 | Return to [mooda.WaterFrame](../waterframe.md). 60 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![mooda header](./docs/img_docs/mooda-header.jpg) 2 | 3 | [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.2677621.svg)](10.5281/zenodo.2643207) 4 | 5 | Mooda is a python package designed mainly for oceanographers and marine science students. It is based on a power scripting system for: 6 | 7 | * open and analyze data files from scientific instrumentation and platforms 8 | * generate data quality control 9 | * make plots that are commonly used in the oceanographic community 10 | * make data files in netCDF and CSV format 11 | 12 | # Why to use mooda and how it works 13 | 14 | In an oceanographic data file, metadata (the definition of data) is almost as relevant as the data. Without them, you do not know what the data means. 15 | 16 | There are libraries, such as pandas, that allow you to manipulate the data quickly, but they do not give you the possibility to save the metadata. 17 | 18 | With mooda, we work with WaterFrames. A WaterFrame object contains a pandas DataFrame and two dictionaries. With a WaterFrame, you can open data files; data is stored into the DataFrame, and the metadata is stored into the dictionaries. With a WaterFrame, you can use the power of a pandas DataFrame without loose all the metadata information. Additionally, mooda helps to open and analyze raw data from scientific instruments and data from oceanographic platforms. 19 | 20 | # Where to get it 21 | 22 | Binary installers for the latest released stable version are available at the [Python package index](https://pypi.org/project/mooda/) 23 | 24 | ```cmd 25 | pip install mooda 26 | ``` 27 | 28 | See more [instructions](docs/installation/installation.md) for installation from sources or non-PyPi releases. 29 | 30 | # Documentation 31 | 32 | The official documentation is hosted here, on the [docs directory](docs/index_docs.md). 33 | 34 | # Projects that use or have used mooda 35 | 36 | ![logos](./docs/img_docs/logos.png) 37 | 38 | # License 39 | 40 | [MIT](LICENSE) 41 | -------------------------------------------------------------------------------- /docs/api_reference/util/emso/get_data.md: -------------------------------------------------------------------------------- 1 | # mooda.emso.get_data(*depth_max*=*None*, *depth_min*=*None*, *depth_qcs*=*[]*, *end_time*=*''*, *metadata_ids*=*[]*, *size*=*10*, *sort*=*'desc'*, *parameters*=*[]*, platform_codes:List[str]=[], start_time:str='', *time_qcs*=*[]*, *value_qcs*=*[]*) 2 | 3 | ## Reference 4 | 5 | Get data from the EMSO ERIC API. 6 | 7 | ### Parameters 8 | 9 | * depth_max: Maximun depth of the measurement (int) 10 | * depth_min: Minimum depth of the measurement (int) 11 | * depth_qcs: List of QC values accepted for the depth_qc field (List[int]) 12 | * end_time: Maximum date of the measurement (str) 13 | * metadata_ids: List of accepted 'metadata_id' (List[str]) 14 | * size: Number of values to be returned (int) 15 | * sort: Options -> 'asc' or 'desc'. Get the first or last (in time) measurements (str) 16 | * parameters: List of accepted 'parameter' (List[str]) 17 | * platform_codes: List of accepted 'platform_code' (List[str]) 18 | * start_time: Minimun date of the meassurement (str) 19 | * time_qcs: List of accepted values for the field time_qc (List[int]) 20 | * value_qcs: List of accepted values for the field of value_qc (List[int]) 21 | 22 | ### Returns 23 | 24 | * data_list: The data (List[dict]) 25 | 26 | ### Example 27 | 28 | ```python 29 | import mooda as md 30 | import pprint # For nice printing 31 | 32 | emso = md.util.EMSO(user='LOGIN', password='PASSWORD') 33 | 34 | metadatas = emso.get_metadata() 35 | for metadata in metadatas: 36 | pprint.pprint(metadata) 37 | ``` 38 | 39 | Output: 40 | 41 | ``` 42 | {'area': 'Mediterranean', 43 | 'depth': '2367.294921875', 44 | 'depth_qc': 0, 45 | 'institution': 'MIO UMR7294 CNRS / OSU Pytheas', 46 | 'location': {'lat': '42.793', 'lon': '6.038'}, 47 | ... 48 | ... 49 | ... 50 | 'time': '2020-11-09 23:31:10', 51 | 'time_qc': 0, 52 | 'units': 'dbar', 53 | 'value': '2195.3310546875', 54 | 'value_qc': 0} 55 | ``` 56 | 57 | Return to [Index](../../index_api_reference.md). 58 | -------------------------------------------------------------------------------- /mooda/waterframe/analysis/pres2depth.py: -------------------------------------------------------------------------------- 1 | """ Implementation of WaterFrame.pres2depth() """ 2 | import numpy as np 3 | 4 | def pres2depth(self, add_nominal_depth=True, density='sea-water', inplace=True): 5 | """ 6 | It creates the DEPTH index of the WaterFrame from the PRES column. 7 | 8 | Parameters 9 | ---------- 10 | add_nominal_depth: bool 11 | Returns a WaterFrame with an extra parameter called 'NOMINAL_DEPTH' 12 | that contains the previous 'DEPTH' values. 13 | density: str 14 | Options: 'sea-water', 'fresh-water', '' 15 | 16 | Returns 17 | ------- 18 | min_dict: dict 19 | Dictionary with the following format: 20 | { 21 | '': , 22 | '': , 23 | 'name of parameter': < min value of parameter> 24 | } 25 | If min_dict is None, all the values of the parameter are NaN. 26 | """ 27 | 28 | df_copy = self.data.copy() 29 | 30 | df_copy = df_copy.reset_index() 31 | 32 | # Add QC flags from PRES 33 | df_copy['DEPTH_QC'] = df_copy['PRES_QC'] 34 | 35 | if add_nominal_depth: 36 | df_copy['NOMINAL_DEPTH'] = df_copy['DEPTH'] 37 | df_copy['NOMINAL_DEPTH_QC'] = df_copy['DEPTH_QC'] 38 | 39 | # Calculation of DEPTH 40 | if isinstance(density, str): 41 | if density == 'sea-water': 42 | dens = 1.114293 43 | elif density == 'fresh-water': 44 | dens = 1.11135 45 | else: 46 | dens = float(density) 47 | else: 48 | # Supose to be a number 49 | dens = density 50 | 51 | df_copy['DEPTH'] = df_copy['PRES'] / dens 52 | df_copy.set_index(['TIME', 'DEPTH'], inplace=True) 53 | 54 | wf_copy = self.copy() 55 | wf_copy.data = df_copy.copy() 56 | 57 | if inplace: 58 | self.data = df_copy.copy() 59 | 60 | return wf_copy 61 | -------------------------------------------------------------------------------- /docs/examples/temp_spain_january_2019.md: -------------------------------------------------------------------------------- 1 | # Comparison of seawater temperature of several observatories using EMODnet data 2 | 3 | In this example, we have used data from [EMODnet Physics](https://www.emodnet-physics.eu/Portal/). We have downloaded all the data from January 2020 from the observatories of the Spanish coast that measure the temperature of the water in the first 5 meters of depth. We have discarded datasets that contain errors (for example, misspelt geolocation). We have also dropped datasets with water temperatures at various depths or with large amounts of data so that the script could be run on less powerful computers. Finally, the files that we are going to use in this example are [here](./data/emodnet-esp-2020-01.7z). 4 | 5 | ```python 6 | import mooda as md 7 | import plotly.graph_objects as go 8 | import os 9 | 10 | # Make a list of file locations 11 | root = '/path/to/directory/' 12 | nc_files = [os.path.join(root, filename) 13 | for root, _, filenames in os.walk(root) 14 | for filename in filenames 15 | if '.nc' in filename] 16 | 17 | # Open the files and make a list of WaterFrames 18 | wf_list = [md.read_nc_emodnet(path) for path in nc_files] 19 | 20 | # Make an interactive map with the observatory locations 21 | fig1 = md.iplot_location(wf_list) 22 | go.Figure(fig1).show() 23 | 24 | # Make an interactive plot with the seawater temperatures of all the WaterFrames 25 | fig2 = md.iplot_timeseries(wf_list, 'TEMP') 26 | go.Figure(fig2).show() 27 | ``` 28 | 29 | Output: 30 | 31 | ![Observatories of the Spanish coast][spanish-observatories] 32 | 33 | ![Spanish coast seawater temperatures][spanish-temp] 34 | 35 | *Note: The script makes two interactive charts. The images shown in this document have been generated by saving the interactive images in a PNG file.* 36 | 37 | Return to the [Index of examples](index_examples.md). 38 | 39 | [spanish-observatories]: ./img_examples/spanish-observatories.png 40 | 41 | [spanish-temp]: ./img_examples/spanish-temp.png -------------------------------------------------------------------------------- /mooda/util/iplot/iplot_timeseries.py: -------------------------------------------------------------------------------- 1 | """ Implementation of WaterFrame.iplot_timeseries() """ 2 | import numpy as np 3 | import plotly.graph_objects as go 4 | 5 | 6 | def iplot_timeseries(list_wf, parameter_to_plot): 7 | """ 8 | It creates a Plotly figure with the time-series of the input parameter. 9 | 10 | Parameters 11 | ---------- 12 | list_wf: List of WaterFrames 13 | List of WaterFrames to be concatenated. 14 | parameter_to_plot: str 15 | Parameters to plot. 16 | 17 | Returns 18 | ------- 19 | figure: dict 20 | Plotly figure dictionary 21 | """ 22 | data = [] 23 | for wf in list_wf: 24 | # Extract data 25 | df = wf.data[parameter_to_plot].dropna().reset_index() 26 | df = df.groupby(['DEPTH', 'TIME'])[parameter_to_plot].mean() 27 | df = df.reset_index() 28 | df.set_index('TIME', inplace=True) 29 | # df.renane(columns={parameter_to_plot: wf.metadata.get('platform_code')}, inplace=True) 30 | 31 | data.append( 32 | go.Scatter(x=df.index, y=df[parameter_to_plot], 33 | # fill="tozeroy", 34 | name=wf.metadata.get('platform_code'))) 35 | 36 | # Layout 37 | y_label = None 38 | 39 | try: 40 | title = list_wf[0].vocabulary[parameter_to_plot]['long_name'] 41 | except KeyError: 42 | title = parameter_to_plot 43 | try: 44 | y_label = list_wf[0].vocabulary[parameter_to_plot]['units'] 45 | except KeyError: 46 | pass 47 | 48 | min_value = np.nanmin(list_wf[-1].data[parameter_to_plot]) 49 | max_value = np.nanmax(list_wf[0].data[parameter_to_plot]) 50 | 51 | layout = { 52 | 'title': title, 53 | 'yaxis': { 54 | # 'range': [min_value, max_value], 55 | 'title': y_label 56 | }, 57 | 'margin': {'l': 50, 'r': 10, 't': 45, 'b': 30} 58 | } 59 | 60 | figure = {"data": data, "layout": layout} 61 | 62 | return figure 63 | -------------------------------------------------------------------------------- /docs/api_reference/waterframe/output/to_nc.md: -------------------------------------------------------------------------------- 1 | # WaterFrame.to_nc(*path*, *nc_format*=*"NETCDF4"*) 2 | 3 | ## Reference 4 | 5 | It saves the WaterFrame into a NetCDF. 6 | 7 | ### Parameters 8 | 9 | * path: Path to save the NetCDF (str). 10 | * nc_format: Specify the NetCDF format (NETCDF3_64BIT, ‘NETCDF3_CLASSIC’, NETCDF4, NETCDF4_CLASSIC) (str). 11 | * NETCDF4: Data is stored in an HDF5 file, using netCDF4 API features. 12 | * NETCDF4_CLASSIC: Data is stored in an HDF5 file, using only netCDF 3 compatible API features. 13 | * NETCDF3_64BIT: 64-bit offset version of the netCDF 3 file format, which fully supports 2+ GB files, but is only compatible with clients linked against netCDF version 3.6.0 or later. 14 | * NETCDF3_CLASSIC: The classic netCDF 3 file format. It does not handle 2+ GB files very well. 15 | 16 | ### Returns 17 | 18 | * True: If the internal functions of this method do not raise any error, the return is always true (bool). 19 | 20 | ## Example 21 | 22 | To reproduce the example, download the NetCDF file [here](http://data.emso.eu/files/emso/obsea/mo/ts/MO_TS_MO_OBSEA.nc) and save it as `example.nc` in the same python script folder. 23 | 24 | ```python 25 | import mooda as md 26 | 27 | path_netcdf = "example.nc" # Path of the NetCDF file 28 | 29 | wf = md.read_nc_emodnet(path_netcdf) 30 | 31 | # Print parameters 32 | print(f"WaterFrame original parameters: {(', ').join(wf.parameters)}") 33 | # Delete all parameters except 'TEMP' 34 | wf2 = wf.use_only('TEMP', inplace=False) 35 | print(f"New WaterFrame parameters: {(', ').join(wf.parameters)}") 36 | 37 | 38 | # Save the new wf into a NetCDF with the name "example_TEMP.nc" 39 | wf2.to_nc("example_TEMP.nc") 40 | print("NetCDF created.") 41 | ``` 42 | 43 | Output: 44 | 45 | ```shell 46 | WaterFrame original parameters: DEPH, ATMS, CNDC, DRYT, PRES, PSAL, SVEL, TEMP, WDIR, WSPD 47 | New WaterFrame parameters: DEPH, ATMS, CNDC, DRYT, PRES, PSAL, SVEL, TEMP, WDIR, WSPD 48 | NetCDF created. 49 | ``` 50 | 51 | Return to [mooda.WaterFrame](../waterframe.md). 52 | -------------------------------------------------------------------------------- /docs/api_reference/waterframe/iplot/iplot_line.md: -------------------------------------------------------------------------------- 1 | # wf.iplot_line(y, x='TIME', marginal_x=None, marginal_y='histogram', color='auto', range_y='auto', line_shape='lineard', rangeslider_visible=True, line_group='DEPTH', **kwds) 2 | 3 | It uses plotly.express.line. 4 | 5 | Each data point is represented as a marker point, whose location is given by the x and y columns of self.data. 6 | 7 | ## Reference 8 | 9 | ### Parameters 10 | 11 | * y: Y axis, column or index of data. (str) 12 | * x: X axis, column or index of data. (str) 13 | * color: Name of a column or index of data. Values from this column are used to assign color to marks. (str) 14 | * If color = 'auto', color = QC column of *y*. 15 | * symbol: Name of a column or index of data. Values from this column are used to assign symbols to marks. (str) 16 | * range_y: \[min value, max value\] of y axes. (list) 17 | * If range_y = 'auto', range is generated between the min and max values of y axes +- 5%. 18 | * line_shape: Line options: 'linear' 'spline', 'vhv', 'hvh', 'vh', 'hv' (str) 19 | * rangeslider_visible: Show a time range slide on the bottom x axes. (bool) 20 | * line_group: Either a name of a column in wf.data, or a pandas Series or array_like object. Values from this column or array_like are used to group rows of data_frame into lines. (str or int or Series or array-like) 21 | * **kwds: Plotly express scatter keywords. (keywords) 22 | 23 | ### Returns 24 | 25 | * fig: (plotly.graph_objects.Figure) 26 | 27 | 28 | ## Example 29 | 30 | For this example we are going to download water temperature data from EMSO platform 68422. We will download 1000 values without specifying the time range or depth. 31 | 32 | ```python 33 | import mooda as md 34 | 35 | wf = md.from_emso(platform_code='68422', parameters=['TEMP'], size=1000) 36 | 37 | fig = wf.iplot_line('TEMP') 38 | fig.show() 39 | ``` 40 | 41 | Output: 42 | 43 | *Note - The output graph is interactive. Below is the figure saved in a png image.* 44 | 45 | ![iplot_line-example](../img_waterframe/iplot_line-example.png) 46 | 47 | Return to [mooda.WaterFrame](../waterframe.md). 48 | -------------------------------------------------------------------------------- /docs/enhanced_qc.md: -------------------------------------------------------------------------------- 1 | # Enhenced QC 2 | 3 | Key | Entry Term | Abbreviated term | Term definition 4 | --- | --- | --- | --- 5 | 0 | no quality control | none | No quality control procedures have been applied to the data value. This is the initial status for all data values entering the working archive. 6 | 1 | good value | good | Good quality data value that is not part of any identified malfunction and has been verified as consistent with real phenomena during the quality control process. 7 | 2 | probably good value | probably_good | Data value that is probably consistent with real phenomena but this is unconfirmed or data value forming part of a malfunction that is considered too 8 | small to affect the overall quality of the data object of 9 | which it is a part. 10 | 3 | probably bad value | probably_bad | Data value recognised as unusual during quality control that forms part of a feature that is probably inconsistent with real phenomena. 11 | 4 | bad value | bad | An obviously erroneous data value. 12 | 5 | changed value | changed | Data value adjusted during quality control. Best practice strongly recommends that the value before the change be preserved in the data or its accompanying metadata. 13 | 6 | value below detection | DB | The level of the measured phenomenon was too small to be quantified by the technique employed to measure it. The accompanying value is the detection limit for the technique or zero if that value is unknown. 14 | 7 | value in excess | excess | The level of the measured phenomenon was too large to be quantified by the technique employed to measure it. The accompanying value is the measurement limit 15 | for the technique. 16 | 8 | interpolated value | interpolated | This value has been derived by interpolation from other values in the data object. 17 | 9 | missing value | missing | The data value is missing. Any accompanying value will be a magic number representing absent data. 18 | A | value phenomenon uncertain | ID_uncertain | There is uncertainty in the description of the measured phenomenon associated with the value such as chemical species or biological entity. 19 | -------------------------------------------------------------------------------- /docs/api_reference/waterframe/output/to_es.md: -------------------------------------------------------------------------------- 1 | # WaterFrame.to_es(*data_index_name*=*'data'*, *metadata_index_name*=*'metadata'*, *summary_index_name*=*'summary'*, *qc_to_ingest*=*[0, 1]*, ***kwargs*) 2 | 3 | ## Reference 4 | 5 | Injestion of the WaterFrame into a ElasticSeach DB. 6 | 7 | ## Parameters 8 | 9 | * data_index_name: Name of the ElasticSearch index that contains the WaterFrame.data documents. (str) 10 | * metadata_index_name: Name of the ElasticSearch index that contains the WaterFrame.metadata documents. (str) 11 | * summary_index_name: Name of the ElasticSearch index that contains the summary documents. (str) 12 | * summary_index_name: Name of the ElasticSearch index that contains the summary documents. (str) 13 | * qc_to_intest: QC Flags of data to be ingested to the ElasticSearch DB. (list of int) 14 | * **kwargs: [Elasticsearch object creation arguments](https://elasticsearch-py.readthedocs.io/en/master/index.html). 15 | 16 | ## Example 17 | 18 | To reproduce the example, download the NetCDF file [here](http://data.emso.eu/files/emso/obsea/mo/ts/2014/MO_TS_MO_OBSEA_201402.nc) and start an ElasticSearch service on localhost:9200. 19 | 20 | ```python 21 | import mooda as md 22 | 23 | path_netcdf = 'MO_TS_MO_OBSEA_201402.nc' # Path of the NetCDF file 24 | 25 | # Create a WaterFrame from the EMODnet NetCDF file. 26 | wf = md.read_nc_emodnet(path_netcdf) 27 | 28 | # Add some mandatory metadata information 29 | wf.metadata['network'] = 'emodnet' 30 | 31 | # Execute the following line to create the ElaticSearch indexes (just the first time) 32 | # md.es_create_indexes() 33 | 34 | wf.to_es() 35 | ``` 36 | 37 | Output: 38 | 39 | ```shell 40 | ATMS from MO_TS_MO_OBSEA_201402 ingested: 0 of 628 41 | ATMS from MO_TS_MO_OBSEA_201402 ingested: 1 of 628 42 | ATMS from MO_TS_MO_OBSEA_201402 ingested: 2 of 628 43 | ATMS from MO_TS_MO_OBSEA_201402 ingested: 3 of 628 44 | ATMS from MO_TS_MO_OBSEA_201402 ingested: 4 of 628 45 | ATMS from MO_TS_MO_OBSEA_201402 ingested: 5 of 628 46 | ATMS from MO_TS_MO_OBSEA_201402 ingested: 6 of 628 47 | ATMS from MO_TS_MO_OBSEA_201402 ingested: 7 of 628 48 | ... 49 | ``` 50 | 51 | Return to [mooda.WaterFrame](../waterframe.md). 52 | -------------------------------------------------------------------------------- /mooda/waterframe/analysis/asal_temp2dens.py: -------------------------------------------------------------------------------- 1 | """ Implementation of WaterFrame.asal_temp2dens() """ 2 | import numpy as np 3 | import gsw 4 | import pandas as pd 5 | 6 | def asal_temp2dens(self, asal_parameter='ASAL', temp_parameter='TEMP', 7 | pres_parameter='PRES', inplace=True): 8 | """ 9 | This function uses the gsw library. 10 | Adds the parameter Absolute Salinity (ASAL) from Practical Salinity (PSAL). 11 | Since PSAL is non-negative by definition, this function changes any 12 | negative input values of SP to be zero. 13 | 14 | Parameters 15 | ---------- 16 | asal_parameter: str 17 | Parameter with valus of Absolute Salinity (g/kg) 18 | temp_parameter: str 19 | Parameter with temperature data (degree_C) 20 | pres_parameter: str 21 | Parameter with values of pressure (dBar) 22 | inplace: bool 23 | If inplace, changes will be applied on self 24 | 25 | Returns 26 | ------- 27 | new_wf: WaterFrame 28 | """ 29 | 30 | df_copy = self.data.copy() 31 | 32 | df_copy['DENS'] = gsw.density.rho(df_copy[asal_parameter], 33 | df_copy[temp_parameter], 34 | df_copy[pres_parameter]) 35 | 36 | # Add QC 37 | df_copy['DENS_QC'] = 1 38 | # QC=0 39 | df_copy.loc[df_copy[f'{asal_parameter}_QC'] == 0, 'DENS_QC'] = 0 40 | df_copy.loc[df_copy[f'{temp_parameter}_QC'] == 0, 'DENS_QC'] = 0 41 | df_copy.loc[df_copy[f'{pres_parameter}_QC'] == 0, 'DENS_QC'] = 0 42 | # QC=4 43 | df_copy.loc[df_copy[f'{asal_parameter}_QC'] == 4, 'DENS_QC'] = 4 44 | df_copy.loc[df_copy[f'{temp_parameter}_QC'] == 4, 'DENS_QC'] = 4 45 | df_copy.loc[df_copy[f'{pres_parameter}_QC'] == 4, 'DENS_QC'] = 4 46 | 47 | new_wf = self.copy() 48 | new_wf.data = df_copy.copy() 49 | # Add vocabulary 50 | new_wf.vocabulary['DENS'] = { 51 | 'long_name': 'In-situ density', 52 | 'units': 'kg/m'} 53 | 54 | if inplace: 55 | self.data = df_copy.copy() 56 | self.vocabulary = new_wf.vocabulary.copy() 57 | 58 | return new_wf 59 | -------------------------------------------------------------------------------- /mooda/waterframe/iplot/iplot_scatter_mapbox.py: -------------------------------------------------------------------------------- 1 | """ Implementation of wf.iplot_scatter_mapbox """ 2 | import plotly.express as px 3 | 4 | 5 | def iplot_scatter_mapbox(self, mapbox_token, color, lat='LATITUDE', 6 | lon='LONGITUDE', range_color='auto', title='auto', 7 | animation_frame=None, zoom=14.5, labels=None, **kwds): 8 | """ 9 | It uses plotly.express.scatter_mapbox(). 10 | It creates a map with a point in each coordinate of the parameter of the 11 | color argument 12 | 13 | Parameters 14 | ---------- 15 | mapbox_token: str 16 | Token of mapbox 17 | color: str 18 | Parameter to be pointed on the map. 19 | lat: str 20 | Parameter with the latitude. 21 | lon: str 22 | Paramter with the longutude. 23 | range_color: List[float] or 'auto' 24 | Range of values for the color scale. 25 | If color_scale is 'auto', the range is the min and max of the color 26 | parameter. 27 | title: str 28 | Title of the figure. 29 | If title is 'auto' 30 | animation_frame: str or None 31 | Parameter to create an animated graph 32 | zoom: float 33 | Initial Zoom value 34 | **kwds: arguments from plotly.express.scatter_mapbox() 35 | 36 | Returns 37 | ------- 38 | fig: 39 | """ 40 | # Connect plotly express with your mapbox token 41 | px.set_mapbox_access_token(mapbox_token) 42 | 43 | if animation_frame: 44 | df = self.data.reset_index() 45 | animation_frame = df[animation_frame].astype(str) 46 | if range_color == 'auto': 47 | range_color = [min(self.data[color]), max(self.data[color])] 48 | if title == 'auto': 49 | title = self.metadata.get('title', '') 50 | 51 | fig = px.scatter_mapbox(self.data, lat=lat, lon=lon, color=color, 52 | zoom=zoom, animation_frame=animation_frame, 53 | range_color=range_color, title=title, labels=labels, 54 | **kwds) 55 | 56 | return fig 57 | -------------------------------------------------------------------------------- /docs/examples/emso-qc-widget.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "metadata": { 3 | "language_info": { 4 | "codemirror_mode": { 5 | "name": "ipython", 6 | "version": 3 7 | }, 8 | "file_extension": ".py", 9 | "mimetype": "text/x-python", 10 | "name": "python", 11 | "nbconvert_exporter": "python", 12 | "pygments_lexer": "ipython3", 13 | "version": "3.8.4-final" 14 | }, 15 | "orig_nbformat": 2, 16 | "kernelspec": { 17 | "name": "python3", 18 | "display_name": "Python 3", 19 | "language": "python" 20 | } 21 | }, 22 | "nbformat": 4, 23 | "nbformat_minor": 2, 24 | "cells": [ 25 | { 26 | "source": [ 27 | "# How to download EMSO data and perform QC data tests with a Jupyter Notebook Widget" 28 | ], 29 | "cell_type": "markdown", 30 | "metadata": {} 31 | }, 32 | { 33 | "source": [ 34 | "This widget is developed with [mooda.widget_emso()](https://github.com/rbardaji/mooda/blob/master/docs/examples/emso-widget.md) and [mooda.widget_qc()](https://github.com/rbardaji/mooda/blob/master/docs/examples/qc-widget.md)." 35 | ], 36 | "cell_type": "markdown", 37 | "metadata": {} 38 | }, 39 | { 40 | "cell_type": "code", 41 | "execution_count": null, 42 | "metadata": {}, 43 | "outputs": [], 44 | "source": [ 45 | "import mooda as md\n", 46 | "\n", 47 | "# Write here the user and password of the EMSO ERIC API\n", 48 | "user_api = ''\n", 49 | "password_api= ''\n", 50 | "# or write the API token\n", 51 | "token_api = ''\n", 52 | "\n", 53 | "wf = md.WaterFrame()\n", 54 | "\n", 55 | "gui = md.widget_emso_qc(wf, user=user_api, password=password_api, token=token_api)\n", 56 | "gui" 57 | ] 58 | }, 59 | { 60 | "source": [ 61 | "Now, we can save the WaterFrame in a file." 62 | ], 63 | "cell_type": "markdown", 64 | "metadata": {} 65 | }, 66 | { 67 | "cell_type": "code", 68 | "execution_count": null, 69 | "metadata": {}, 70 | "outputs": [], 71 | "source": [ 72 | "gui_save = md.widget_save(wf)\n", 73 | "gui_save" 74 | ] 75 | }, 76 | { 77 | "cell_type": "code", 78 | "execution_count": null, 79 | "metadata": {}, 80 | "outputs": [], 81 | "source": [] 82 | } 83 | ] 84 | } -------------------------------------------------------------------------------- /docs/api_reference/waterframe/plot/plot_timeseries.md: -------------------------------------------------------------------------------- 1 | # wf.plot_timeseries(*parameters_to_plot*=*None*, *qc_flags*=*None*, *rolling_window*=*None*, *ax*=*None*, *average_time*=*None*, *secondary_y*=*None*, *color*=*None*) 2 | 3 | ## Reference 4 | 5 | Plot the input parameters with time on X and the parameters on Y. It calculates the standar deviation of a rolling window and plot it. 6 | 7 | ### Parameters 8 | 9 | * parameters_to_plot: Parameters of the WaterFrame to plot. If parameters_to_plot is None, all parameters will be ploted. (list of str, str) 10 | * qc_flags: QC flags of the parameters to plot. If qc_flags in None, all QC flags will be used. (list of int) 11 | * rolling_window: Size of the moving window. It is the number of observations used for calculating the statistic.(int) 12 | * ax: It is used to add the plot to an input axes object. (matplotlib.axes object) 13 | * average_time: It calculates an average value of a time interval. You can find all of the resample options [here](http://pandas.pydata.org/pandas-docs/stable/timeseries.html#offset-aliases). (str) 14 | * secondary_y: Plot on the secondary y-axis. (bool) 15 | * color: Any matplotlib color. It will be applied to the traces. (str or list of str) 16 | 17 | ### Returns 18 | 19 | * ax: Axes of the plot. (matplotlib.AxesSubplot) 20 | 21 | ## Example 22 | 23 | To reproduce the example, download the NetCDF file [here](http://data.emso.eu/files/emso/obsea/mo/ts/2014/MO_TS_MO_OBSEA_201401.nc) and save it as `example.nc` in the same pyhon script folder. 24 | 25 | ```python 26 | import matplotlib.pyplot as plt 27 | import mooda as md 28 | 29 | path_netcdf = 'example.nc' # Path of the NetCDF file 30 | 31 | wf = md.read_nc_emodnet(path_netcdf) 32 | 33 | # Plot the sea water temperature 34 | wf.plot_timeseries('TEMP') 35 | plt.show() 36 | ``` 37 | 38 | Output: 39 | 40 | ![Plot timeseries example][plot-timeseries-example] 41 | 42 | Notes: In this case, "depth: 1.0" means 20 meters of depth. The underwater laboratory OBSEA only measures the seawater temperature at one unique depth, at 20 meters. 43 | 44 | Return to [mooda.WaterFrame](../waterframe.md). 45 | 46 | [plot-timeseries-example]: ../img_waterframe/plot-timeseries-example.png 47 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | # setup.py 2 | """Setup config to install mooda""" 3 | 4 | from setuptools import setup, find_packages 5 | 6 | NAME = 'mooda' 7 | VERSION = '2.0.0' 8 | DESCRIPTION = 'Module for Ocean Observatory Data Analysis' 9 | LONG_DESCRIPTION = """ 10 | MOODA - Module for Ocean Observatory Data Analysis 11 | 12 | Mooda is a Python package designed mainly for oceanographers and marine science students. 13 | It provides tools to: 14 | 15 | - Open and analyze data files from scientific instrumentation and platforms 16 | - Perform data quality control 17 | - Create plots commonly used in the oceanographic community 18 | - Export data files in netCDF and CSV formats 19 | 20 | Documentation: https://github.com/rbardaji/mooda 21 | """ 22 | CLASSIFIERS = [ 23 | 'Development Status :: 5 - Production/Stable', 24 | 'Environment :: Console', 25 | 'Natural Language :: English', 26 | 'License :: OSI Approved :: MIT License', 27 | 'Programming Language :: Python :: 3.8', 28 | 'Programming Language :: Python :: 3.9', 29 | 'Programming Language :: Python :: 3.10', 30 | 'Programming Language :: Python :: 3.11', 31 | 'Topic :: Software Development :: Libraries :: Python Modules', 32 | 'Topic :: Scientific/Engineering :: Physics', 33 | 'Intended Audience :: Education', 34 | 'Intended Audience :: Science/Research', 35 | 'Intended Audience :: Developers', 36 | ] 37 | KEYWORDS = ['ocean', 'sea', 'EMODnet', 'EMSO'] 38 | URL = 'https://github.com/rbardaji/mooda' 39 | AUTHOR = 'Raul Bardaji Benach' 40 | AUTHOR_EMAIL = 'rbardaji@gmail.com' 41 | LICENSE = 'MIT' 42 | 43 | # Load requirements from the requirements.txt file 44 | with open('requirements.txt') as f: 45 | INSTALL_REQUIRES = f.read().splitlines() 46 | 47 | setup( 48 | name=NAME, 49 | version=VERSION, 50 | description=DESCRIPTION, 51 | long_description=LONG_DESCRIPTION, 52 | long_description_content_type='text/markdown', 53 | classifiers=CLASSIFIERS, 54 | keywords=KEYWORDS, 55 | url=URL, 56 | author=AUTHOR, 57 | author_email=AUTHOR_EMAIL, 58 | license=LICENSE, 59 | packages=find_packages(), 60 | python_requires='>=3.8', 61 | install_requires=INSTALL_REQUIRES, 62 | include_package_data=True, 63 | zip_safe=False, 64 | ) 65 | -------------------------------------------------------------------------------- /docs/code_structure/rbardaji_mooda_mooda.md: -------------------------------------------------------------------------------- 1 | # Directory: rbardaji/mooda/mooda 2 | 3 | It contains the code of the package. 4 | 5 | The mooda/mooda directory structure is as follows: 6 | 7 | * input: A directory that contains function codes that allow you to read data files to access data APIs and get WaterFrame objects. 8 | * util: A directory that contains function codes that are not directly related to a WaterFrame object or are not the WaterFrame methods. For example, the code for making the Jupyter Notebook Widgets or the functionalities that need one or more WaterFrame objects as an input variable is here. 9 | * waterframe: Contains the code generated by the WaterFrame object and its methods. 10 | * __init__.py: File required to create the mooda package from the mooda/mooda directory. Contains the necessary imports to be able to access all files with code. 11 | 12 | The methods of the mooda classes are written in separate files. In this way, adding new methods to a class is simple and does not jeopardize the operation of other methods already written. 13 | 14 | The following is an example of how classes have been created in mooda. The example creates the Foo class, using the 'bar' and 'other' methods. The script main.py imports the Foo class and calls the Foo methods. 15 | 16 | **File structure**: 17 | 18 | ``` 19 | main.py (file) 20 | foo (directory) 21 | |- __init__.py 22 | |- bar.py 23 | |- other.py 24 | ``` 25 | 26 | **\_\_init__.py**: 27 | 28 | This file defines the class and imports the methods that are in the bar.py and other.py. 29 | 30 | ```python 31 | class Foo: 32 | 33 | from .bar import bar 34 | from .other import other 35 | 36 | def __init__(self, a, b): 37 | self.a = a 38 | self.b = b 39 | 40 | ``` 41 | 42 | **bar.py**: 43 | 44 | ```python 45 | def bar(self, a): 46 | return f'a is {a}' 47 | ``` 48 | 49 | **other.py**: 50 | 51 | ```python 52 | def other(self, b): 53 | return f'b is {b}' 54 | ``` 55 | 56 | **main.py**: 57 | 58 | ```python 59 | from foo import Foo 60 | 61 | a = 1 62 | b = 2 63 | 64 | foo_main = Foo(a, b) 65 | 66 | print('Return of Foo.bar():', foo_main.bar()) 67 | print('Return of Foo.other():', foo_main.other()) 68 | ``` 69 | 70 | Output: 71 | 72 | ``` 73 | Return of Foo.bar(): a is 1 74 | Return of Foo.other(): b is 2 75 | ``` 76 | 77 | Return to the documentation of the [rbardaji/mooda](rbardaji_mooda.md) folder. -------------------------------------------------------------------------------- /mooda/waterframe/qc/qc_replace.py: -------------------------------------------------------------------------------- 1 | """ Implementation of wf.qc_replace() """ 2 | import numpy as np 3 | 4 | 5 | def qc_replace(self, parameters=None, to_replace=0, value=1, start=0, inplace=True): 6 | """ 7 | Replace the values of QC from the input parameters. 8 | 9 | Parameters 10 | ---------- 11 | parameters: None, str or list of str. 12 | List of parameters to change the values of QC. Ex: ['TEMP', 'PSAL']. 13 | to_replace: int 14 | QC value to replace. 15 | value: int 16 | Value to replace any values matching to_replace with. 17 | inplace: bool 18 | If inplace, makes changes inplace and returns True. 19 | Otherwhise, returns a new WaterFrame. 20 | 21 | Returns 22 | ------- 23 | new_wf: WaterFrame 24 | """ 25 | def change_signals(signals): 26 | # Change flags 27 | result = [] 28 | for i, signal in enumerate(signals): 29 | if i < start: 30 | result.append(signal) 31 | else: 32 | if signal == to_replace: 33 | result.append(value) 34 | else: 35 | result.append(signal) 36 | 37 | return np.array(result) 38 | 39 | if parameters is None: 40 | parameters = self.parameters 41 | elif isinstance(parameters, str): 42 | parameters = [parameters] 43 | 44 | data = self.data.copy() 45 | 46 | for parameter in parameters: 47 | 48 | # New 49 | df = data[[parameter, f'{parameter}_QC']].reset_index() 50 | df.set_index('TIME', inplace=True) 51 | 52 | try: 53 | for depth, df_depth in df.groupby('DEPTH'): 54 | df_depth.sort_index(inplace=True) 55 | 56 | signals = df_depth[f'{parameter}_QC'].values 57 | 58 | # Change flags 59 | result = change_signals(signals) 60 | 61 | # Asignation of result with numpy array due to 62 | # AttributeError: 'list' object has no attribute 'ravel' 63 | data.loc[(depth,), f'{parameter}_QC'] = np.array(result) 64 | except KeyError: 65 | # No Depth 66 | signals = df[f'{parameter}_QC'].values 67 | 68 | # Change flags 69 | result = change_signals(signals) 70 | 71 | data[f'{parameter}_QC'] = result 72 | 73 | if inplace: 74 | self.data = data 75 | return True 76 | else: 77 | new_wf = self.copy() 78 | new_wf.data = data 79 | return new_wf -------------------------------------------------------------------------------- /docs/api_reference/waterframe/qc/qc_spike_test.md: -------------------------------------------------------------------------------- 1 | # WaterFrame.qc_spike_test(*parameters*=*None*, *window*=*0*, *threshold*=*3*, *influence*=*0.5*, *flag*=*4*, *inplace*=*True*) 2 | 3 | ## Reference 4 | 5 | Based on [peak signal detection in realtime timeseries data](https://stackoverflow.com/questions/22583391/peak-signal-detection-in-realtime-timeseries-data). 6 | 7 | Algorithm based on the principle of dispersion: if a new datapoint is a given x number of standard deviations away from some moving mean, the algorithm signals (also called z-score). The algorithm is very robust because it constructs a separate moving mean and deviation, such that signals do not corrupt the threshold. Future signals are therefore identified with approximately the same accuracy, regardless of the amount of previous signals. 8 | 9 | For example, a window of 5 will use the last 5 observations to smooth the data. A threshold of 3.5 will signal if a datapoint is 3.5 standard deviations away from the moving mean. And an influence of 0.5 gives signals half of the influence that normal datapoints have. Likewise, an influence of 0 ignores signals completely for recalculating the new threshold. An influence of 0 is therefore the most robust option (but assumes stationarity); putting the influence option at 1 is least robust. For non-stationary data, the influence option should therefore be put somewhere between 0 and 1. 10 | 11 | ### Parameters 12 | 13 | * parameters: Key of self.data to apply the test. (string or list of strings) 14 | * window: The lag of the moving window. Minimun value = 3. If it is 0, the window is the 10% of the length of data with a maximum value of 100. (int) 15 | * threshold: The z-score at which the algorithm signals. (float) 16 | * influence: The influence (between 0 and 1) of new signals on the mean and standard deviation. (float) 17 | * flag: Flag value to write on the signal values. (int) 18 | * inplace: If True, it changes the flags in place and returns True. Otherwhise it returns an other WaterFrame. (bool) 19 | 20 | ### Returns 21 | 22 | * new_wf: WaterFrame 23 | 24 | ## Example 25 | 26 | To reproduce the example, download the NetCDF file [here](http://data.emso.eu/files/emso/obsea/mo/ts/MO_TS_MO_OBSEA.nc) and save it as `example.nc` in the same python script folder. 27 | 28 | ```python 29 | import mooda as md 30 | 31 | path_netcdf = "MO_TS_MO_OBSEA_201401.nc" # Path of the NetCDF file 32 | 33 | wf = md.read_nc_emodnet(path_netcdf) 34 | 35 | ok = wf.qc_spike_test() 36 | 37 | if ok: 38 | print('Spike test applied.') 39 | ``` 40 | 41 | Output: 42 | 43 | ```shell 44 | Spike test applied. 45 | ``` 46 | 47 | Return to [mooda.WaterFrame](../waterframe.md). 48 | -------------------------------------------------------------------------------- /docs/api_reference/waterframe/iplot/iplot_scatter.md: -------------------------------------------------------------------------------- 1 | # wf.iplot_scatter(*y*, *x*=*'TIME'*, *trendline*=*None*, *marginal_x*=*None*, *marginal_y*=*'histogram'*, *color*=*'auto'*, *symbol*=*'DEPTH'*, *range_y*=*'auto'*, ***kwds*) 2 | 3 | It makes an interactive scatter plot. 4 | 5 | ## Reference 6 | 7 | ### Parameters 8 | 9 | * y: Y axis, column or index of data. (str) 10 | * x: X axis, column or index of data. (str) 11 | * trendline: (str) 12 | * Options: 13 | * None 14 | * 'ols': Ordinary Least Squares regression line will be drawn for each discrete-color/symbol group. 15 | * 'ols_np': Ordinary Least Squares regression line will be drawn for each discrete-color/symbol group. Line generated with numpy.polyfit with all values of y axes. 16 | * 'lowess': Locally Weighted Scatterplot Smoothing line will be drawn for each discrete-color/symbol group. 17 | * marginal_x: If set, a horizontal subplot is drawn above the main plot, visualizing the x-distribution. (str) 18 | * Options: 19 | * None 20 | * 'rug' 21 | * 'box' 22 | * 'violin' 23 | * 'histogram' 24 | * marginal_y: If set, a horizontal subplot is drawn above the main plot, visualizing the y-distribution. (str) 25 | * Options: 26 | * None 27 | * 'rug' 28 | * 'box' 29 | * 'violin' 30 | * 'histogram' 31 | * color: Name of a column or index of data. Values from this column are used to assign color to marks. (str) 32 | * If color = 'auto', color = QC column of *y*. 33 | * symbol: Name of a column or index of data. Values from this column are used to assign symbols to marks. (str) 34 | * range_y: \[min value, max value\] of y axes. (list) 35 | * If range_y = 'auto', range is generated between the min and max values of y axes +- 5%. 36 | * **kwds: Plotly express scatter keywords. (keywords) 37 | 38 | ### Returns 39 | 40 | * fig: (plotly.graph_objects.Figure) 41 | 42 | 43 | ## Example 44 | 45 | To reproduce the example, download the NetCDF file [MO_TS_MO_OBSEA_201402.nc](http://data.emso.eu/files/emso/obsea/mo/ts/2014/MO_TS_MO_OBSEA_201402.nc). 46 | 47 | ```python 48 | import mooda as md 49 | 50 | path_netcdf = "MO_TS_MO_OBSEA_201402.nc" # Path of the NetCDF file 51 | wf = md.read_nc_emodnet(path_netcdf) 52 | 53 | fig = wf.iplot_scatter('TEMP', marginal_y='histogram') 54 | fig.show() 55 | ``` 56 | 57 | Output: 58 | 59 | The output of this script is an interactive graph that cannot be displayed on the GitHub environment. To get the interactive chart, download and run this script on your computer. Below you will find the chart exported to png. 60 | 61 | ![iplot_scatter-example](../img_waterframe/iplot_scatter-example.png) 62 | 63 | Return to [mooda.WaterFrame](../waterframe.md). 64 | -------------------------------------------------------------------------------- /mooda/waterframe/plot/plot_hist.py: -------------------------------------------------------------------------------- 1 | """ 2 | Implementation of WaterFrame.plot_hist(parameter=None, mean_line=False, **kwds) 3 | """ 4 | 5 | def plot_hist(self, parameters=None, mean_line=False, **kwds): 6 | """ 7 | Make a histogram of the WaterFrame's. 8 | A histogram is a representation of the distribution of data. 9 | This function calls pandas.DataFrame.hist(), on each parameter of the 10 | WaterFrame, resulting in one histogram per parameter. 11 | 12 | Parameters 13 | ---------- 14 | parameters: str, list of str, optional (parameters=None) 15 | keys of self.data to plot. If parameters=None, it will plot all 16 | parameters. 17 | mean_line: bool, optional (mean_line=False) 18 | It draws a line representing the average of the values. 19 | **kwds: 20 | All other plotting keyword arguments to be passed to 21 | DataFrame.hist(). 22 | https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.hist.html 23 | Returns 24 | ------- 25 | ax: matplotlib.AxesSubplot 26 | Axes of the plot. 27 | """ 28 | 29 | if parameters is None: 30 | parameters = list(self.parameters) 31 | 32 | if isinstance(parameters, str): 33 | parameters = [parameters] 34 | 35 | axes = self.data.hist(column=parameters, **kwds) 36 | parameter_counter = 0 37 | try: 38 | for ax in axes: 39 | ax.set_xlabel("Values") 40 | ax.set_ylabel("Frequency") 41 | if mean_line is True: 42 | if parameter_counter < len(parameters): 43 | x_mean = self.mean(parameters[parameter_counter]) 44 | ax.axvline(x_mean, color='k', 45 | linestyle='dashed', 46 | linewidth=1) 47 | 48 | parameter_counter += 1 49 | except AttributeError: 50 | 51 | # Creation of the mean line 52 | parameter_counter = 0 53 | for irow in range(len(axes)): 54 | for icol in range(len(axes[irow])): 55 | if parameter_counter < len(parameters): 56 | axes[irow, icol].set_xlabel("Values") 57 | axes[irow, icol].set_ylabel("Frequency") 58 | if mean_line is True: 59 | x_mean = self.data[axes[irow, icol].get_title()].mean() 60 | axes[irow, icol].axvline(x_mean, color='k', 61 | linestyle='dashed', 62 | linewidth=1) 63 | parameter_counter += 1 64 | 65 | return axes 66 | -------------------------------------------------------------------------------- /mooda/waterframe/analysis/resample.py: -------------------------------------------------------------------------------- 1 | """ Implementation of WaterFrame.resample(rule, method='mean') """ 2 | import pandas as pd 3 | 4 | def resample(self, rule, method='mean', inplace=True): 5 | """ 6 | Convenience method for frequency conversion and sampling of time series of the WaterFrame 7 | object. Warning: if WaterFrame.data contains MultiIndex, those indexes will disappear, obtaining a single 'TIME' 8 | index. 9 | 10 | Parameters 11 | ---------- 12 | rule: str 13 | The offset string or object representing target conversion. 14 | You can find all of the resample options here: 15 | http://pandas.pydata.org/pandas-docs/stable/timeseries.html#offset-aliases 16 | method: "mean", "max", "min", optional, (method = "mean") 17 | Save the new value with the mean(), max() or min() function. 18 | inplace: bool 19 | If True, resample in place and return 'True', If False, return a new WaterFrame. 20 | 21 | Returns 22 | ------- 23 | new_wf: WaterFrame 24 | """ 25 | if isinstance(self.data.index, 26 | pd.MultiIndex) and 'DEPTH' in self.data.index.names: 27 | 28 | # pd.Grouper allows you to specify a "groupby instruction for a target 29 | # object". 30 | # Ref: https://stackoverflow.com/questions/15799162/resampling-within-a-pandas-multiindex 31 | level_values = self.data.index.get_level_values 32 | 33 | if method == "mean": 34 | data = ( 35 | self.data.groupby( 36 | [level_values(0)] + # 0 is 'DEPTH' 37 | [pd.Grouper(freq=rule, level='TIME')]).mean()) 38 | elif method == "max": 39 | data = ( 40 | self.data.groupby( 41 | [level_values(0)] + # 0 is 'DEPTH' 42 | [pd.Grouper(freq=rule, level='TIME')]).max()) 43 | elif method == "min": 44 | data = ( 45 | self.data.groupby( 46 | [level_values(0)] + # 0 is 'DEPTH' 47 | [pd.Grouper(freq=rule, level='TIME')]).min()) 48 | else: 49 | # Legacy 50 | if method == "mean": 51 | data = self.data.resample(rule, level='TIME').mean() 52 | elif method == "max": 53 | data = self.data.resample(rule, level='TIME').max() 54 | elif method == "min": 55 | data = self.data.resample(rule, level='TIME').min() 56 | 57 | # Change "_QC" values to 0 58 | for key in self.data.keys(): 59 | if "_QC" in key: 60 | data[key] = 0 61 | 62 | if inplace: 63 | self.data = data 64 | return True 65 | else: 66 | new_wf = self.copy() 67 | new_wf.data = data 68 | return new_wf 69 | -------------------------------------------------------------------------------- /docs/api_reference/waterframe/analysis/info_metadata.md: -------------------------------------------------------------------------------- 1 | # WaterFrame.info_metadata(*keys*=*None*) 2 | 3 | ## Reference 4 | 5 | It returns a formatted string with the metadata information. 6 | 7 | ### Parameters 8 | 9 | * keys: Keys of WaterFrame.metadata (str or list of str) 10 | 11 | ### Returns 12 | 13 | * message: Message with the metadata information. (str) 14 | 15 | ## Example 16 | 17 | To reproduce the example, download the NetCDF file [MO_TS_MO_OBSEA_201401.nc](http://data.emso.eu/files/emso/obsea/mo/ts/2014/MO_TS_MO_OBSEA_201401.nc) and save it in the same python script folder. 18 | 19 | ```python 20 | import mooda as md 21 | 22 | path = "MO_TS_MO_OBSEA_201401.nc" # Path to the NetCDF file 23 | 24 | wf = md.read_nc_emodnet(path) 25 | 26 | print(wf.info_metadata()) 27 | ``` 28 | 29 | Output: 30 | 31 | ```shell 32 | - platform_code: OBSEA 33 | - institution: SARTI Research Group. Electronics Dept. Universitat Politecnica de Catalunya (UPC) 34 | - institution_edmo_code: 2150 35 | - date_update: 2019-07-08T10:11:04Z 36 | - site_code: OBSEA 37 | - source: moored surface buoy 38 | - history: 2018-01-18T13:39:07Z : Creation 39 | - data_mode: R 40 | - references: http://www.oceansites.org, http://marine.copernicus.eu 41 | - id: MO_TS_MO_OBSEA_201401 42 | - area: Mediterranean 43 | - geospatial_lat_min: 41.182 44 | - geospatial_lat_max: 41.182 45 | - geospatial_lon_min: 1.75235 46 | - geospatial_lon_max: 1.75235 47 | - geospatial_vertical_min: -3.0 48 | - geospatial_vertical_max: 21.0 49 | - time_coverage_start: 2014-01-19T00:00:00Z 50 | - time_coverage_end: 2014-01-31T23:00:00Z 51 | - institution_references: http://www.obsea.es/, http://cdsarti.org/ 52 | - contact: Daniel Mihai Toma, daniel.mihai.toma@upc.edu, cmems-service@hcmr.gr 53 | - author: Universitat Politecnica de Catalunya (UPC), Med ROOS data center (HCMR) 54 | - pi_name: Joaquin del Rio, joaquin.del.rio@upc.edu 55 | - update_interval: daily 56 | - qc_manual: OceanSITES User's Manual v1.2 57 | - data_type: OceanSITES time-series data 58 | - netcdf_version: netCDF-4 classic model 59 | - naming_authority: OceanSITES 60 | - cdm_data_type: Time-series 61 | - quality_control_indicator: 6 62 | - distribution_statement: These data follow Copernicus standards; they are public and free of charge. User assumes all risk for use of data. User must display citation in any publication or product using data. User must contact PI prior to any commercial use of data. 63 | - quality_index: A 64 | - citation: These data were collected and made freely available by the Copernicus project and the programs that contribute to it 65 | - format_version: 1.2 66 | - Conventions: CF-1.6 OceanSITES-Manual-1.2 Copernicus-InSituTAC-SRD-1.4 Copernicus-InSituTAC-ParametersList-3.1.0 67 | - title: Med Sea - NRT in situ Observations 68 | - data_assembly_center: HCMR 69 | - last_latitude_observation: 41.182 70 | - last_longitude_observation: 1.75235 71 | - last_date_observation: 2014-01-31T23:00:00Z 72 | ``` 73 | 74 | Return to [mooda.WaterFrame](../waterframe.md). 75 | -------------------------------------------------------------------------------- /docs/api_reference/waterframe/qc/formula_cheat.md: -------------------------------------------------------------------------------- 1 | $\alpha$ \alpha 2 | 3 | $A$ A 4 | 5 | $\beta$ \beta 6 | 7 | $B$ B 8 | 9 | $\gamma$ \gammma 10 | 11 | $\Gamma$ \Gamma 12 | 13 | $\pi$ \pi 14 | 15 | $\Pi$ \Pi 16 | 17 | $\phi$ \phi 18 | 19 | $\Phi$ \Phi 20 | 21 | $\varphi$ \varphi 22 | 23 | $\theta$ 24 | 25 | $\cos$ \cos 26 | 27 | $\sin$ \sin 28 | 29 | $\lim$ \lim 30 | 31 | $\exp$ \exp 32 | 33 | $\to$ \to 34 | 35 | $\infty$ \infty 36 | 37 | $\equiv$ \equiv 38 | 39 | $\bmod$ \bmod 40 | 41 | $\times$ 42 | 43 | $k_{n+1}$ k_{n+1} 44 | 45 | $n^2$ n^2 46 | 47 | $k_n^2$ k_n^2 48 | 49 | $\frac{n!}{k!(n-k)!}$ \frac{n!}{k!(n-k)!} 50 | 51 | $\binom{n}{k}$ \binom{n}{k} 52 | 53 | $\frac{\frac{x}{1}}{x - y}$ \frac{\frac{x}{1}}{x - y} 54 | 55 | $^3/_7$ 56 | 57 | $\sqrt{k}$ \sqrt{k} 58 | 59 | $\sqrt[n]{k}$ \sqrt[n]{k} 60 | 61 | $\sum_{i=1}^{10} t_i$ \sum_{i=1}^{10} t_i 62 | 63 | $\int_0^\infty \mathrm{e}^{-x},\mathrm{d}x$ \int_0^\infty \mathrm{e}^{-x},\mathrm{d}x 64 | 65 | $\sum$ \sum 66 | 67 | $\prod$ \prod 68 | 69 | $\coprod$ \coprod 70 | 71 | $\bigoplus$ \bigoplus 72 | 73 | $\bigotimes$ \bigotimes 74 | 75 | $\bigodot$ \bigodot 76 | 77 | $\bigcup$ \bigcup 78 | 79 | $\bigcap$ \bigcap 80 | 81 | $\biguplus$ \biguplus 82 | 83 | $\bigsqcup$ \bigsqcup 84 | 85 | $\bigvee$ \bigvee 86 | 87 | $\bigwedge$ \bigwedge 88 | 89 | $\int$ \int 90 | 91 | $\oint$ \oint 92 | 93 | $\iint$ \iint 94 | 95 | $\iiint$ \iiint 96 | 97 | $\idotsint$ \idotsint 98 | 99 | $\sum_{\substack{0 TIME , temperature -> TEMP , etc? 65 | # TODO Should this method include arguments to request ERDDAP server side operations ? Ej. orderBy, orderByClosest, orderByMean, etc? 66 | 67 | return WaterFrame(df=_df, 68 | metadata=remote.info, 69 | vocabulary=_vocabulary) 70 | -------------------------------------------------------------------------------- /mooda/waterframe/iplot/iplot_candlestick.py: -------------------------------------------------------------------------------- 1 | from stockstats import StockDataFrame 2 | import plotly.graph_objects as go 3 | 4 | 5 | def iplot_candlestick(self, parameter="", interval="", show_macd=False, 6 | xaxis_rangeslider_visible=False, title="", **kargs): 7 | """ 8 | It uses https://plotly.com/python/candlestick-charts/. 9 | 10 | The candlestick chart is a style of financial chart describing open, high, 11 | low and close for a given x coordinate (most likely time). The boxes 12 | represent the spread between the open and close values and the lines 13 | represent the spread between the low and high values. Sample points 14 | where the close value is higher (lower) then the open value are called 15 | increasing (decreasing). By default, increasing candles are drawn in 16 | green whereas decreasing are drawn in red. 17 | 18 | Parameters 19 | ---------- 20 | parameter: str 21 | Parameter of self.data 22 | interval: 23 | Interval for the candlestick boxes 24 | show_macd: bool 25 | Show the MACD indicator (Moving Average Convergence Divergence) 26 | """ 27 | 28 | df = self.data.copy() 29 | df.reset_index(inplace=True) 30 | df.set_index(['TIME'], inplace=True) 31 | 32 | if parameter and interval: 33 | 34 | df_min = df.resample(interval).min() 35 | df_max = df.resample(interval).max() 36 | df_open = df.resample(interval).first() 37 | df_close = df.resample(interval).last() 38 | 39 | df = df_min.copy() 40 | df['low'] = df_min[parameter].copy() 41 | df['high'] = df_max[parameter].copy() 42 | df['open'] = df_open[parameter].copy() 43 | df['close'] = df_close[parameter].copy() 44 | 45 | 46 | if show_macd: 47 | df = StockDataFrame.retype(df) 48 | 49 | df['macd'] = df.get('macd') # calculate MACD 50 | 51 | df['0'] = 0 52 | 53 | fig = go.Figure( 54 | data=[go.Candlestick( 55 | x=df.index, 56 | open=df['open'], 57 | high=df['high'], 58 | low=df['low'], 59 | close=df['close'])]) 60 | 61 | if show_macd: 62 | fig.add_trace( 63 | go.Scatter( 64 | x=df.index, 65 | y=df['0'], 66 | line = dict(color='black'), 67 | name='0', 68 | showlegend=False)) 69 | 70 | fig.add_trace( 71 | go.Scatter( 72 | x=df.index, 73 | y=df['macd'], 74 | line=dict(color='blue'), 75 | name='macd')) 76 | 77 | fig.add_trace( 78 | go.Scatter( 79 | x=df.index, 80 | y=df['macds'], 81 | line=dict(color='orange'), 82 | name='macds')) 83 | 84 | fig.add_trace( 85 | go.Bar( 86 | x=df.index, 87 | y=df['macdh'], 88 | name='macdh')) 89 | 90 | fig.update_layout( 91 | xaxis_rangeslider_visible=xaxis_rangeslider_visible, 92 | title=title) 93 | 94 | return fig 95 | -------------------------------------------------------------------------------- /mooda/waterframe/output/html_templates/metadata.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | {{ metadata_dict['id'] }} 9 | 10 | 11 | 13 | 14 | 17 | 20 | 21 | 22 | 24 |

25 |

26 | {{ metadata_dict['id'] }} 27 |

28 |

29 | 30 |
31 | 32 | 33 | {% for key, value in metadata_dict.items() %} 34 | 35 | 36 | 37 | 38 | {% endfor %} 39 |
{{ key }}{{ value }}
40 | 41 |
42 |

43 | 44 | {{ footer_text }} 45 | 46 |

47 |
48 | 49 | 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /mooda/waterframe/plot/plot_timebar.py: -------------------------------------------------------------------------------- 1 | """ Implementation of WaterFrame.plot_bar(key, ax=None, average_time=None)""" 2 | import datetime 3 | 4 | def plot_timebar(self, keys, ax=None, time_interval_mean=None, ylim='auto'): 5 | """ 6 | Make a bar plot of the input keys. 7 | The bars are positioned at x with date/time. Their dimensions are given by height. 8 | 9 | Parameters 10 | ---------- 11 | keys: list of str 12 | keys of self.data to plot. 13 | ax: matplotlib.axes object, optional (ax = None) 14 | It is used to add the plot to an input axes object. 15 | time_interval_mean: str, optional (time_interval_mean = None) 16 | It calculates an average value of a time interval. You can find 17 | all of the resample options here: 18 | https://pandas.pydata.org/pandas-docs/stable/user_guide/timeseries.html 19 | ylim: 2-tuple/list, None, 'auto' 20 | Y axis limit. If ylim = 'auto' 21 | Returns 22 | ------- 23 | ax: matplotlib.AxesSubplot 24 | Axes of the plot. 25 | """ 26 | 27 | def format_year(x): 28 | return datetime.datetime.\ 29 | strptime(x, '%Y-%m-%d %H:%M:%S').strftime('%Y') 30 | 31 | def format_day(x): 32 | return datetime.datetime.\ 33 | strptime(x, '%Y-%m-%d %H:%M:%S').strftime('%Y-%m-%d') 34 | 35 | # Extract data 36 | df = self.data[keys].dropna().reset_index().set_index('TIME') 37 | df.index.rename("Date", inplace=True) 38 | 39 | # Delete DEPTH, we are not going to use it in this case 40 | if 'DEPTH' in df.keys(): 41 | del df['DEPTH'] 42 | 43 | # Resample data 44 | if time_interval_mean is None: 45 | pass 46 | else: 47 | df = df.resample(time_interval_mean).mean() 48 | 49 | # Get min and max values for ylim 50 | if ylim == 'auto': 51 | # df.min() returns a Series or DataFrame with the min of each column 52 | y_min = min(df.min().values) 53 | y_max = max(df.max().values) 54 | y_percent = (y_max - y_min) / 100 55 | ylim = (y_min - 5 * y_percent, y_max + 5 * y_percent) 56 | 57 | if isinstance(keys, list): 58 | ax = df[keys].plot.bar(ax=ax, legend=True, ylim=ylim) 59 | else: 60 | ax = df[keys].plot.bar(ax=ax, ylim=ylim) 61 | # Write axes 62 | try: 63 | ax.set_ylabel(self.vocabulary[keys]['units']) 64 | except KeyError: 65 | print("Warning: We don't know the units of", keys, 66 | "Please, add info into self.meaning[", keys, "['units']") 67 | 68 | if time_interval_mean == 'A': 69 | ax.set_xticklabels([format_year(x.get_text()) 70 | for x in ax.get_xticklabels()], rotation=60) 71 | elif time_interval_mean == 'D': 72 | ax.set_xticklabels([format_day(x.get_text()) 73 | for x in ax.get_xticklabels()], rotation=60) 74 | elif time_interval_mean == 'M': 75 | ax.set_xticklabels([format_day(x.get_text()) 76 | for x in ax.get_xticklabels()], rotation=60) 77 | 78 | return ax 79 | -------------------------------------------------------------------------------- /mooda/waterframe/analysis/psal2asal.py: -------------------------------------------------------------------------------- 1 | """ Implementation of WaterFrame.psal2asal() """ 2 | import numpy as np 3 | import gsw 4 | import pandas as pd 5 | 6 | def psal2asal(self, psal_parameter='PSAL', pres_parameter='PRES', lon='auto', 7 | lat='auto', inplace=True): 8 | """ 9 | This function uses the gsw library. 10 | Adds the parameter Absolute Salinity (ASAL) from Practical Salinity (PSAL). 11 | Since PSAL is non-negative by definition, this function changes any 12 | negative input values of SP to be zero. 13 | 14 | Parameters 15 | ---------- 16 | psal_parameter: str 17 | Parameter with valus of Practical Salinity 18 | pres_parameter: str 19 | Parameter with values of pressure, in dBar 20 | lon: str 21 | Parameter with the values of the longitud, in degrees 22 | If lon is 'auto', the value of lon will be taken from the 23 | metadata['last_longitude_observation'] 24 | lat: str 25 | Parameter with the values of the ñatitude, in degrees 26 | If lat is 'auto', the value of lon will be taken from the 27 | metadata['last_latitude_observation'] 28 | 29 | Returns 30 | ------- 31 | wf: WaterFrame 32 | """ 33 | 34 | df_copy = self.data.copy() 35 | if lat == 'auto': 36 | lat_parameter = 'LATITUDE' 37 | df_copy['LATITUDE'] = float(self.metadata['last_latitude_observation']) 38 | df_copy['LATITUDE_QC'] = 1 39 | else: 40 | lat_parameter = lat 41 | if lon == 'auto': 42 | lon_parameter = 'LONGITUDE' 43 | df_copy['LONGITUDE'] = float(self.metadata['last_longitude_observation']) 44 | df_copy['LONGITUDE_QC'] = 1 45 | else: 46 | lon_parameter = 'lon' 47 | 48 | df_copy['ASAL'] = gsw.SA_from_SP(df_copy[psal_parameter], 49 | df_copy[pres_parameter], 50 | df_copy[lon_parameter], 51 | df_copy[lat_parameter]) 52 | 53 | # Add QC 54 | df_copy['ASAL_QC'] = 1 55 | # QC=0 56 | df_copy.loc[df_copy[f'{psal_parameter}_QC'] == 0, 'ASAL_QC'] = 0 57 | df_copy.loc[df_copy[f'{pres_parameter}_QC'] == 0, 'ASAL_QC'] = 0 58 | df_copy.loc[df_copy[f'{lon_parameter}_QC'] == 0, 'ASAL_QC'] = 0 59 | df_copy.loc[df_copy[f'{lat_parameter}_QC'] == 0, 'ASAL_QC'] = 0 60 | # QC=4 61 | df_copy.loc[df_copy[f'{psal_parameter}_QC'] == 4, 'ASAL_QC'] = 4 62 | df_copy.loc[df_copy[f'{pres_parameter}_QC'] == 4, 'ASAL_QC'] = 4 63 | df_copy.loc[df_copy[f'{lon_parameter}_QC'] == 4, 'ASAL_QC'] = 4 64 | df_copy.loc[df_copy[f'{lat_parameter}_QC'] == 4, 'ASAL_QC'] = 4 65 | 66 | # Delete lat and lon 67 | if lat == 'auto': 68 | del df_copy[f'{lat_parameter}_QC'] 69 | del df_copy[lat_parameter] 70 | if lon == 'auto': 71 | del df_copy[f'{lon_parameter}_QC'] 72 | del df_copy[lon_parameter] 73 | 74 | new_wf = self.copy() 75 | new_wf.data = df_copy.copy() 76 | # Add vocabulary 77 | new_wf.vocabulary['ASAL'] = { 78 | 'long_name': 'Absolute Salinity', 79 | 'units': 'g/kg'} 80 | 81 | if inplace: 82 | self.data = df_copy.copy() 83 | self.vocabulary = new_wf.vocabulary.copy() 84 | 85 | return new_wf 86 | -------------------------------------------------------------------------------- /mooda/waterframe/analysis/reduce_memory.py: -------------------------------------------------------------------------------- 1 | """ Implementation of WaterFrame.reduce_memory() """ 2 | import numpy as np 3 | 4 | 5 | def reduce_memory(self, inplace=True): 6 | """ 7 | Data in a WaterFrame is saved in a pandas DataFrame. By default, the obtained dataset can be 8 | very heavy in memory because column types of the pandas DataFrame are defined to accept heavy 9 | value types. This method redefine the column types ad typically reduced the dataset size in 10 | memory by 30% - 50%. 11 | Ref: https://www.kaggle.com/arjanso/reducing-dataframe-memory-size-by-65 12 | 13 | Parameters 14 | ---------- 15 | inplace: bool 16 | If false, the method will return a new WaterFrame. Otherwise, it returns True 17 | """ 18 | 19 | def reduce_mem_usage(props): 20 | 21 | NAlist = [] # Keeps track of columns that have missing values filled in. 22 | for col in props.columns: 23 | if props[col].dtype != object: # Exclude strings 24 | 25 | # make variables for Int, max and min 26 | IsInt = False 27 | mx = props[col].max() 28 | mn = props[col].min() 29 | 30 | # test if column can be converted to an integer 31 | asint = props[col].fillna(0).astype(np.int64) 32 | result = (props[col] - asint) 33 | result = result.sum() 34 | if result > -0.01 and result < 0.01: 35 | IsInt = True 36 | 37 | try: 38 | # Make Integer/unsigned Integer datatypes 39 | if IsInt: 40 | if mn >= 0: 41 | if mx < 255: 42 | props[col] = props[col].astype(np.uint8) 43 | elif mx < 65535: 44 | props[col] = props[col].astype(np.uint16) 45 | elif mx < 4294967295: 46 | props[col] = props[col].astype(np.uint32) 47 | else: 48 | props[col] = props[col].astype(np.uint64) 49 | else: 50 | if mn > np.iinfo(np.int8).min and mx < np.iinfo(np.int8).max: 51 | props[col] = props[col].astype(np.int8) 52 | elif mn > np.iinfo(np.int16).min and mx < np.iinfo(np.int16).max: 53 | props[col] = props[col].astype(np.int16) 54 | elif mn > np.iinfo(np.int32).min and mx < np.iinfo(np.int32).max: 55 | props[col] = props[col].astype(np.int32) 56 | elif mn > np.iinfo(np.int64).min and mx < np.iinfo(np.int64).max: 57 | props[col] = props[col].astype(np.int64) 58 | 59 | # Make float datatypes 32 bit 60 | else: 61 | props[col] = props[col].astype(np.float32) 62 | except ValueError: 63 | # There are nans 64 | props[col] = props[col].astype(np.float32) 65 | 66 | return props, NAlist 67 | 68 | df = self.data.copy() 69 | df, _ = reduce_mem_usage(df) 70 | 71 | if inplace: 72 | self.data = df.copy() 73 | else: 74 | wf = self.copy() 75 | wf.data = df.copy() 76 | return wf 77 | -------------------------------------------------------------------------------- /mooda/waterframe/iplot/iplot_scatter.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import plotly.express as px 3 | import plotly.graph_objects as go 4 | 5 | 6 | def iplot_scatter(self, y, x='TIME', trendline=None, marginal_x=None, marginal_y='histogram', 7 | color='auto', symbol='DEPTH', range_y='auto', **kwds): 8 | """ 9 | It uses plotly.express.scatter. 10 | Each data point is represented as a marker point, whose location is given by the x and y columns 11 | of self.data. 12 | 13 | Parameters 14 | ---------- 15 | y: str 16 | Y axis, column or index of data. 17 | x: str 18 | X axis, column or index of data. 19 | trendline: str 20 | Options: 21 | None 22 | 'ols': Ordinary Least Squares regression line will be drawn for each 23 | discrete-color/symbol group. 24 | 'ols_np': Ordinary Least Squares regression line will be drawn for each 25 | discrete-color/symbol group. 26 | Line generated with numpy.polyfit with all values of y axes. 27 | 'lowess': Locally Weighted Scatterplot Smoothing line will be drawn for each 28 | discrete-color/symbol group. 29 | marginal_x: str 30 | If set, a horizontal subplot is drawn above the main plot, visualizing the 31 | x-distribution. 32 | Options: None, 'rug', 'box', 'violin', or 'histogram'. 33 | marginal_y: str 34 | If set, a horizontal subplot is drawn above the main plot, visualizing the 35 | y-distribution. 36 | Options: None, 'rug', 'box', 'violin', or 'histogram'. 37 | color: str 38 | Name of a column or index of data. Values from this column are used to assign color to 39 | marks. If color = 'auto', color = QC column of y. 40 | symbol: str 41 | Name of a column or index of data. Values from this column are used to assign symbols to 42 | marks. 43 | range_y: list 44 | [min value, max value] of y axes. If range_y = 'auto', range is generated between the 45 | min and max values of y axes +- 5%. 46 | **kwds: keywords 47 | plotly express scatter keywords. 48 | 49 | Returns 50 | ------- 51 | fig: plotly.graph_objects.Figure 52 | """ 53 | df = pd.DataFrame() 54 | _df = self.data.reset_index() 55 | 56 | df[y] = _df[y] 57 | df[x] = _df[x] 58 | 59 | # Range Y calculation 60 | y_min = min(df[y].values) 61 | y_max = max(df[y].values) 62 | y_percent = (y_max - y_min) / 100 63 | 64 | if range_y == 'auto': 65 | range_y = [y_min - 5* y_percent, y_max + 5* y_percent] 66 | 67 | if color == 'auto': 68 | color = f'{y}_QC' 69 | df[color] = _df[color].astype('str') 70 | elif color: 71 | df[color] = _df[color] 72 | 73 | if symbol == 'DEPTH': 74 | df[symbol] = _df[symbol].astype('str') 75 | elif symbol: 76 | df[symbol] = _df[symbol] 77 | 78 | # Save memory 79 | del _df 80 | 81 | # Dropna 82 | df.dropna(inplace=True) 83 | 84 | # Sort index TIME 85 | df.set_index('TIME', inplace=True) 86 | df.sort_index(inplace=True) 87 | df.reset_index(inplace=True) 88 | 89 | fig = px.scatter( 90 | df, x=x, y=y, trendline=trendline, marginal_x=marginal_x, marginal_y=marginal_y, 91 | color=color, symbol=symbol, range_y=range_y, **kwds) 92 | 93 | return fig 94 | --------------------------------------------------------------------------------