From de4eaceacd7f74cb2411c01a859f3f4ea63fb19d Mon Sep 17 00:00:00 2001 From: hjabbot <42661345+hjabbot@users.noreply.github.com> Date: Mon, 16 Oct 2023 15:34:02 +0100 Subject: [PATCH 01/39] git status --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 8a605813..603292ea 100644 --- a/requirements.txt +++ b/requirements.txt @@ -12,6 +12,6 @@ scikit-learn scipy tqdm xarray -cartopy +# cartopy rasterio From 2a383553b9d2c77eeb85d8e0d8c12f63ead9f5ac Mon Sep 17 00:00:00 2001 From: hjabbot <42661345+hjabbot@users.noreply.github.com> Date: Mon, 16 Oct 2023 15:35:30 +0100 Subject: [PATCH 02/39] Removing cartopy for pipeline --- meshiphi/mesh_plotting/mesh_plotter.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/meshiphi/mesh_plotting/mesh_plotter.py b/meshiphi/mesh_plotting/mesh_plotter.py index 4635489e..e9e1dfb4 100644 --- a/meshiphi/mesh_plotting/mesh_plotter.py +++ b/meshiphi/mesh_plotting/mesh_plotter.py @@ -1,5 +1,4 @@ -import cartopy -import cartopy.crs as ccrs +# import cartopy.crs as ccrs import shapely from shapely.geometry import Point, Polygon import matplotlib @@ -28,7 +27,7 @@ def __init__(self, mesh_json, figscale=10): self.fig = plt.figure(figsize=(self.figscale * self.aspect_ratio, self.figscale)) - self.plot = plt.axes(projection=ccrs.PlateCarree()) + # self.plot = plt.axes(projection=ccrs.PlateCarree()) self.plot.set_extent([self.long_min, self.long_max, self.lat_min, self.lat_max]) @@ -42,7 +41,7 @@ def plot_bool(self, value_name, colour): for cellbox in self.mesh_json['cellboxes']: polygon = shapely.wkt.loads(cellbox['geometry']) if cellbox[value_name] == True: - self.plot.add_geometries([polygon], ccrs.PlateCarree(), facecolor=colour, alpha=1.0, edgecolor='darkslategrey') + # self.plot.add_geometries([polygon], ccrs.PlateCarree(), facecolor=colour, alpha=1.0, edgecolor='darkslategrey') def plot_cmap(self, value_name, colourmap): """ @@ -64,7 +63,7 @@ def plot_cmap(self, value_name, colourmap): # normalise value normalized_value = (cellbox[value_name] - value_min) / value_diff polygon = shapely.wkt.loads(cellbox['geometry']) - self.plot.add_geometries([polygon], ccrs.PlateCarree(), facecolor=cmap(normalized_value), alpha=1.0, edgecolor='darkslategrey') + # self.plot.add_geometries([polygon], ccrs.PlateCarree(), facecolor=cmap(normalized_value), alpha=1.0, edgecolor='darkslategrey') def save(self, filename): """ From 80ac22f542ae64f3aa20ed48b7bf6a89035f1352 Mon Sep 17 00:00:00 2001 From: polarroute Date: Fri, 20 Oct 2023 13:35:08 +0100 Subject: [PATCH 03/39] Fixing deprecated functionality --- meshiphi/dataloaders/scalar/icenet.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meshiphi/dataloaders/scalar/icenet.py b/meshiphi/dataloaders/scalar/icenet.py index eb14e3fb..596f639e 100644 --- a/meshiphi/dataloaders/scalar/icenet.py +++ b/meshiphi/dataloaders/scalar/icenet.py @@ -41,7 +41,7 @@ def filename_to_datetime(filename): for file in self.files if filename_to_datetime(file) < min_time} # Find closest date prior to min_time - closest_date = max(k for k, v in file_dates.iteritems()) + closest_date = max(k for k, v in file_dates.items()) # Open Dataset ds = xr.open_dataset(file_dates[closest_date]) From 411d0ed07f9dd752c8f0cae496cd30305e88de01 Mon Sep 17 00:00:00 2001 From: hjabbot <42661345+hjabbot@users.noreply.github.com> Date: Sat, 4 Nov 2023 10:02:35 +0000 Subject: [PATCH 04/39] New dataloader for ECMWF SWH grib2 files --- .../scalar/ecmwf_sig_wave_height.py | 97 +++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 meshiphi/dataloaders/scalar/ecmwf_sig_wave_height.py diff --git a/meshiphi/dataloaders/scalar/ecmwf_sig_wave_height.py b/meshiphi/dataloaders/scalar/ecmwf_sig_wave_height.py new file mode 100644 index 00000000..683ebf64 --- /dev/null +++ b/meshiphi/dataloaders/scalar/ecmwf_sig_wave_height.py @@ -0,0 +1,97 @@ +from meshiphi.dataloaders.scalar.abstract_scalar import ScalarDataLoader +from datetime import datetime, timedelta +import logging +import os +import xarray as xr + +class ECMWFWaveDataLoader(ScalarDataLoader): + + def import_data(self, bounds): + ''' + Reads in data from a ECMWF GRIB2 file, or folder of files. + Extracts Significant wave height + + Args: + bounds (Boundary): Initial boundary to limit the dataset to + + Returns: + xr.Dataset: + ECMWF SWH dataset within limits of bounds. + Dataset has coordinates 'lat', 'long', and variable 'SIC' + ''' + def extract_base_date(filename): + filename = os.path.basename(filename) + base_date = filename.split('-')[0] + base_date = datetime.strptime(base_date, '%Y%m%d%H0000') + return base_date + + def calculate_timestamp(filename): + ''' + Get date from filename in format: + YYYYMMDDHH0000-wave-fc.grib2 + ''' + # Get filename independant of directory + filename = os.path.basename(filename) + # Get date of file and forecast timedelta + base_date, forecast_len, _, _ = filename.split('-') + # Turn forecast len into number of hours + forecast_len = int(forecast_len[:-1]) + # Calculate + date = datetime.strptime(base_date, '%Y%m%d%H0000') + \ + timedelta(hours=forecast_len) + return date + + def retrieve_data(filename, timestamp): + ''' + Read in data as xr.Dataset, create time coordinate + ''' + data = xr.open_dataset(filename) + # Add date to data + data = data.assign_coords(time=timestamp) + return data + + # Date limits + start_time = datetime.strptime(bounds.get_time_min(), '%Y-%m-%d') + end_time = datetime.strptime(bounds.get_time_max(), '%Y-%m-%d') + + # Go through reverse alphabetical list until date < start_date found + self.files = sorted(self.files, reverse=True) + for file in self.files: + base_date = extract_base_date(file) + if base_date < start_time: + closest_date = base_date + break + # If none found, raise error + else: + raise FileNotFoundError('No file found prior to start time') + # Limit files to be read in + self.files = [file for file in self.files + if extract_base_date(file) == closest_date] + + data_array = [] + relevant_files = [] + # Limit data to forecasts that cover time boundary + for file in self.files: + timestamp = calculate_timestamp(file) + print(start_time, timestamp, end_time) + if start_time <= timestamp <= end_time: + data_array.append(retrieve_data(file, timestamp)) + relevant_files += [file] + # Concat all valid files + if len(data_array) == 0: + logging.error('\tNo files found for date range '+\ + f'[ {bounds.get_time_min()} : {bounds.get_time_max()} ]') + raise FileNotFoundError('No ECMWF Wave files found within specified time range!') + data = xr.concat(data_array,'time') + + # Extract just SWH + data = data['swh'].to_dataset() + data = data.rename({'latitude':'lat', + 'longitude':'long'}) + + data = data.reindex(lat=data.lat[::-1]) + data = data.reset_coords(drop=True) + # Limit self.files to only those actually used + self.files = relevant_files + + return data From 438b19f9cb51db558b82c09d1a5ae37844b33216 Mon Sep 17 00:00:00 2001 From: hjabbot <42661345+hjabbot@users.noreply.github.com> Date: Sat, 4 Nov 2023 10:05:13 +0000 Subject: [PATCH 05/39] Finalising ECMWF SWH dataloader --- meshiphi/dataloaders/factory.py | 2 ++ meshiphi/dataloaders/scalar/ecmwf_sig_wave_height.py | 2 +- requirements.txt | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/meshiphi/dataloaders/factory.py b/meshiphi/dataloaders/factory.py index 16be330b..929454e8 100644 --- a/meshiphi/dataloaders/factory.py +++ b/meshiphi/dataloaders/factory.py @@ -14,6 +14,7 @@ from meshiphi.dataloaders.scalar.era5_mean_wave_direction import ERA5MeanWaveDirDataLoader from meshiphi.dataloaders.scalar.era5_wind_mag import ERA5WindMagDataLoader from meshiphi.dataloaders.scalar.era5_wind_dir import ERA5WindDirDataLoader +from meshiphi.dataloaders.scalar.ecmwf_sig_wave_height import ECMWFSigWaveHeightDataLoader from meshiphi.dataloaders.vector.baltic_current import BalticCurrentDataLoader from meshiphi.dataloaders.vector.era5_wind import ERA5WindDataLoader @@ -93,6 +94,7 @@ def get_dataloader(name, bounds, params, min_dp=5): 'era5_wave_period': (ERA5WavePeriodDataLoader, ['files']), 'era5_wind_mag': (ERA5WindMagDataLoader, ['files']), 'era5_wind_dir': (ERA5WindDirDataLoader, ['files']), + 'ecmwf_sig_wave_height': (ECMWFSigWaveHeightDataLoader, ['files']), # Scalar - Abstract shapes 'circle': (ShapeDataLoader, []), 'square': (ShapeDataLoader, []), diff --git a/meshiphi/dataloaders/scalar/ecmwf_sig_wave_height.py b/meshiphi/dataloaders/scalar/ecmwf_sig_wave_height.py index 683ebf64..4e3d895c 100644 --- a/meshiphi/dataloaders/scalar/ecmwf_sig_wave_height.py +++ b/meshiphi/dataloaders/scalar/ecmwf_sig_wave_height.py @@ -4,7 +4,7 @@ import os import xarray as xr -class ECMWFWaveDataLoader(ScalarDataLoader): +class ECMWFSigWaveHeightDataLoader(ScalarDataLoader): def import_data(self, bounds): ''' diff --git a/requirements.txt b/requirements.txt index 82f1eeee..1d241e8c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,6 +3,7 @@ geopandas jsonschema matplotlib netcdf4 +cfgrib numpy>=1.21.6,<=1.24.1 pandas>=1.3.5,<=1.4.4 pytest From 7e1c62f307dabf2545b555217c36f25c63b569b6 Mon Sep 17 00:00:00 2001 From: hjabbot <42661345+hjabbot@users.noreply.github.com> Date: Tue, 23 Jan 2024 15:40:03 +0000 Subject: [PATCH 06/39] Revert "Removing cartopy for pipeline" This reverts commit 2a383553b9d2c77eeb85d8e0d8c12f63ead9f5ac. --- meshiphi/mesh_plotting/mesh_plotter.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/meshiphi/mesh_plotting/mesh_plotter.py b/meshiphi/mesh_plotting/mesh_plotter.py index e9e1dfb4..4635489e 100644 --- a/meshiphi/mesh_plotting/mesh_plotter.py +++ b/meshiphi/mesh_plotting/mesh_plotter.py @@ -1,4 +1,5 @@ -# import cartopy.crs as ccrs +import cartopy +import cartopy.crs as ccrs import shapely from shapely.geometry import Point, Polygon import matplotlib @@ -27,7 +28,7 @@ def __init__(self, mesh_json, figscale=10): self.fig = plt.figure(figsize=(self.figscale * self.aspect_ratio, self.figscale)) - # self.plot = plt.axes(projection=ccrs.PlateCarree()) + self.plot = plt.axes(projection=ccrs.PlateCarree()) self.plot.set_extent([self.long_min, self.long_max, self.lat_min, self.lat_max]) @@ -41,7 +42,7 @@ def plot_bool(self, value_name, colour): for cellbox in self.mesh_json['cellboxes']: polygon = shapely.wkt.loads(cellbox['geometry']) if cellbox[value_name] == True: - # self.plot.add_geometries([polygon], ccrs.PlateCarree(), facecolor=colour, alpha=1.0, edgecolor='darkslategrey') + self.plot.add_geometries([polygon], ccrs.PlateCarree(), facecolor=colour, alpha=1.0, edgecolor='darkslategrey') def plot_cmap(self, value_name, colourmap): """ @@ -63,7 +64,7 @@ def plot_cmap(self, value_name, colourmap): # normalise value normalized_value = (cellbox[value_name] - value_min) / value_diff polygon = shapely.wkt.loads(cellbox['geometry']) - # self.plot.add_geometries([polygon], ccrs.PlateCarree(), facecolor=cmap(normalized_value), alpha=1.0, edgecolor='darkslategrey') + self.plot.add_geometries([polygon], ccrs.PlateCarree(), facecolor=cmap(normalized_value), alpha=1.0, edgecolor='darkslategrey') def save(self, filename): """ From 8e8765eeae61a75464521855e316a21f31458248 Mon Sep 17 00:00:00 2001 From: hjabbot <42661345+hjabbot@users.noreply.github.com> Date: Tue, 23 Jan 2024 15:40:36 +0000 Subject: [PATCH 07/39] Revert "git status" This reverts commit de4eaceacd7f74cb2411c01a859f3f4ea63fb19d. --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 1d241e8c..187c7388 100644 --- a/requirements.txt +++ b/requirements.txt @@ -13,6 +13,6 @@ scikit-learn scipy tqdm xarray -# cartopy +cartopy rasterio From fccc02ec1505f54d6dd731ac8eaba0ce129fbcce Mon Sep 17 00:00:00 2001 From: hjabbot <42661345+hjabbot@users.noreply.github.com> Date: Tue, 23 Jan 2024 16:11:54 +0000 Subject: [PATCH 08/39] Updating version number --- meshiphi/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meshiphi/__init__.py b/meshiphi/__init__.py index 57bcc3a3..b204ad56 100644 --- a/meshiphi/__init__.py +++ b/meshiphi/__init__.py @@ -1,4 +1,4 @@ -__version__ = "1.1.5" +__version__ = "1.1.6" __description__ = "meshiphi: Earth's digital twin mapped on a non-uniform mesh" __license__ = "MIT" From 0bc567fb8820238da9e008cb474c87b5132c387a Mon Sep 17 00:00:00 2001 From: George Date: Wed, 24 Jan 2024 15:41:12 +0000 Subject: [PATCH 09/39] Add visual_ice dataloader --- meshiphi/dataloaders/factory.py | 2 ++ meshiphi/dataloaders/scalar/visual_ice.py | 34 +++++++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 meshiphi/dataloaders/scalar/visual_ice.py diff --git a/meshiphi/dataloaders/factory.py b/meshiphi/dataloaders/factory.py index 16be330b..17bf389d 100644 --- a/meshiphi/dataloaders/factory.py +++ b/meshiphi/dataloaders/factory.py @@ -14,6 +14,7 @@ from meshiphi.dataloaders.scalar.era5_mean_wave_direction import ERA5MeanWaveDirDataLoader from meshiphi.dataloaders.scalar.era5_wind_mag import ERA5WindMagDataLoader from meshiphi.dataloaders.scalar.era5_wind_dir import ERA5WindDirDataLoader +from meshiphi.dataloaders.scalar.visual_ice import VisualIceDataLoader from meshiphi.dataloaders.vector.baltic_current import BalticCurrentDataLoader from meshiphi.dataloaders.vector.era5_wind import ERA5WindDataLoader @@ -87,6 +88,7 @@ def get_dataloader(name, bounds, params, min_dp=5): 'gebco': (GEBCODataLoader, ['files']), 'icenet': (IceNetDataLoader, ['files']), 'modis': (MODISDataLoader, ['files']), + 'visual_ice': (VisualIceDataLoader, ['files']), 'era5_sig_wave_height': (ERA5SigWaveHeightDataLoader, ['files']), 'era5_max_wave_height': (ERA5MaxWaveHeightDataLoader, ['files']), 'era5_wave_dir': (ERA5MeanWaveDirDataLoader, ['files']), diff --git a/meshiphi/dataloaders/scalar/visual_ice.py b/meshiphi/dataloaders/scalar/visual_ice.py new file mode 100644 index 00000000..42a87cf4 --- /dev/null +++ b/meshiphi/dataloaders/scalar/visual_ice.py @@ -0,0 +1,34 @@ +from meshiphi.dataloaders.scalar.abstract_scalar import ScalarDataLoader + +import logging +import xarray as xr + + +class VisualIceDataLoader(ScalarDataLoader): + def import_data(self, bounds): + """ + Reads in data from Visual_Ice NetCDF files. Renames coordinates to + 'lat' and 'long'. + + Args: + bounds (Boundary): Initial boundary to limit the dataset to + + Returns: + xr.Dataset: + visual_ice dataset within limits of bounds. + Dataset has coordinates 'lat', 'long', and variable 'SIC' + """ + # Import data from files defined in config + if len(self.files) == 1: + visual_ice = xr.open_dataset(self.files[0]) + else: + visual_ice = xr.open_mfdataset(self.files) + + # Remove unnecessary columns + visual_ice = visual_ice.drop_vars('polar_stereographic') + + # Transform columns to standard format + visual_ice = visual_ice.rename({'Band1': 'SIC'}) + visual_ice = visual_ice.assign(SIC=lambda x: x.SIC * 100) + + return visual_ice From 8bc0ea89513db1fbfde16481802c7ef016dcd3de Mon Sep 17 00:00:00 2001 From: Samuel Hall <96304883+SamuelHall700@users.noreply.github.com> Date: Thu, 1 Feb 2024 16:13:48 +0000 Subject: [PATCH 10/39] Updating visual_ice dataloader to accept .tiff images --- meshiphi/dataloaders/scalar/visual_ice.py | 66 ++++++++++++++++++++--- 1 file changed, 60 insertions(+), 6 deletions(-) diff --git a/meshiphi/dataloaders/scalar/visual_ice.py b/meshiphi/dataloaders/scalar/visual_ice.py index 42a87cf4..8c3b8055 100644 --- a/meshiphi/dataloaders/scalar/visual_ice.py +++ b/meshiphi/dataloaders/scalar/visual_ice.py @@ -2,6 +2,7 @@ import logging import xarray as xr +import pandas as pd class VisualIceDataLoader(ScalarDataLoader): @@ -21,14 +22,67 @@ def import_data(self, bounds): # Import data from files defined in config if len(self.files) == 1: visual_ice = xr.open_dataset(self.files[0]) + # If the file is a tiff, use the import_from_tiff method + if self.files[0].split('.')[-1] == 'tiff': + visual_ice = self.import_from_tiff(visual_ice) + elif self.files[0].split('.')[-1] == 'nc': + visual_ice = self.import_from_nc(visual_ice) + else: + logging.error('File type not supported') + return None else: visual_ice = xr.open_mfdataset(self.files) + visual_ice = self.import_from_nc(visual_ice) - # Remove unnecessary columns - visual_ice = visual_ice.drop_vars('polar_stereographic') + return visual_ice - # Transform columns to standard format - visual_ice = visual_ice.rename({'Band1': 'SIC'}) - visual_ice = visual_ice.assign(SIC=lambda x: x.SIC * 100) + def import_from_nc(self, xarray_dataset): + """ + applys transformations need to import a netcdf file - return visual_ice + Args: + xarray_dataset (xr.Dataset): dataset to be transformed + + Returns: + xr.Dataset: transformed dataset + """ + # drop unnecessary variables + xarray_dataset = xarray_dataset.drop_vars('polar_stereographic') + + # rename variables + xarray_dataset = xarray_dataset.rename({'Band1': 'SIC'}) + + # convert SIC to percentage + xarray_dataset = xarray_dataset.assign(SIC=lambda x: x.SIC * 100) + + return xarray_dataset + + def import_from_tiff(self, xarray_dataset): + """ + applys transformations need to import a tiff file + + Args: + xarray_dataset (xr.Dataset): dataset to be transformed + + Returns: + xr.Dataset: transformed dataset + """ + vi_dataframe = xarray_dataset.to_dataframe().reset_index() + # drop unnecessary columns + vi_dataframe = vi_dataframe.drop(columns=['band', 'spatial_ref']) + + # rename columns + vi_dataframe = vi_dataframe.rename(columns={'band_data': 'SIC'}) + + # convert SIC to percentage + vi_dataframe['SIC'] = vi_dataframe['SIC'] * 100 + + # convert back to xarray + vi_dataframe = vi_dataframe.set_index(['x', 'y']) + vi_dataset = vi_dataframe.to_xarray() + + return vi_dataset + + + + From 04b135cc0ccdf11927f8ae1644f91e1e911c13c9 Mon Sep 17 00:00:00 2001 From: Samuel Hall <96304883+SamuelHall700@users.noreply.github.com> Date: Tue, 13 Feb 2024 09:56:22 +0000 Subject: [PATCH 11/39] adding visual_iced section to docs --- .../scalar/implemented/visual_iced.rst | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 docs/source/sections/Dataloaders/scalar/implemented/visual_iced.rst diff --git a/docs/source/sections/Dataloaders/scalar/implemented/visual_iced.rst b/docs/source/sections/Dataloaders/scalar/implemented/visual_iced.rst new file mode 100644 index 00000000..9dc7b0b2 --- /dev/null +++ b/docs/source/sections/Dataloaders/scalar/implemented/visual_iced.rst @@ -0,0 +1,16 @@ +************************* +Visual_ice Dataloader +************************* + +Visual_ice is a dataloader for .tiff images generated from the visual_ice library, +developed my Martin Rodgers at the British Antarctic Surveys AI Lab. The Visual_iced +images are ice/water binary files, generated from a combination of MODIS and SAR +satelite imagery. + +In the source data, 0's are representaive of open water, and 1's are representative of +ice. In the dataloader, we map theses values to Sea ice concentration, in range of 0 to 100. +Values between 0 and 100 are achived by the aggregation of the 0's and 1's which each cell. + +.. automodule:: meshiphi.dataloaders.scalar.visual_ice + :special-members: __init__ + :members: \ No newline at end of file From ee0bf6a482052dd9c3cca956d8bca3fa6ea7ab87 Mon Sep 17 00:00:00 2001 From: Samuel Hall <96304883+SamuelHall700@users.noreply.github.com> Date: Tue, 13 Feb 2024 10:01:42 +0000 Subject: [PATCH 12/39] updating version number --- meshiphi/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meshiphi/__init__.py b/meshiphi/__init__.py index 57bcc3a3..b204ad56 100644 --- a/meshiphi/__init__.py +++ b/meshiphi/__init__.py @@ -1,4 +1,4 @@ -__version__ = "1.1.5" +__version__ = "1.1.6" __description__ = "meshiphi: Earth's digital twin mapped on a non-uniform mesh" __license__ = "MIT" From b65a3a25c7f83900f48b587d830f36a0761fd7f7 Mon Sep 17 00:00:00 2001 From: hjabbot <42661345+hjabbot@users.noreply.github.com> Date: Tue, 13 Feb 2024 14:25:05 +0000 Subject: [PATCH 13/39] Added docs for new grib dataloader --- .../scalar/implemented/ECMWFSigWaveHeight.rst | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 docs/source/sections/Dataloaders/scalar/implemented/ECMWFSigWaveHeight.rst diff --git a/docs/source/sections/Dataloaders/scalar/implemented/ECMWFSigWaveHeight.rst b/docs/source/sections/Dataloaders/scalar/implemented/ECMWFSigWaveHeight.rst new file mode 100644 index 00000000..0f7ad265 --- /dev/null +++ b/docs/source/sections/Dataloaders/scalar/implemented/ECMWFSigWaveHeight.rst @@ -0,0 +1,21 @@ +***************************** +ECMWFSigWaveHeight Dataloader +***************************** + +The ECMWF (European Centre for Medium-Range Weather Forecasts) are both a +research institute and a 24/7 operational service, producing global numerical +weather predictions and other data for their Member and Co-operating States +and the broader community. The Centre has one of the largest supercomputer +facilities and meteorological data archives in the world. Other strategic +activities include delivering advanced training and assisting the WMO in +implementing its programmes. +(description taken from `here `_) + +Data can be downloaded from `here `_ + +This dataloader is for the grib2 files. + + +.. automodule:: meshiphi.dataloaders.scalar.ecmwf_sig_wave_height + :special-members: __init__ + :members: \ No newline at end of file From 15ac26ae5434bfff8d0c3643625f511fea2eee4a Mon Sep 17 00:00:00 2001 From: Samuel Hall <96304883+SamuelHall700@users.noreply.github.com> Date: Tue, 13 Feb 2024 14:26:09 +0000 Subject: [PATCH 14/39] correcting spelling mistakes in docs --- .../scalar/implemented/{visual_iced.rst => visual_ice.rst} | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) rename docs/source/sections/Dataloaders/scalar/implemented/{visual_iced.rst => visual_ice.rst} (75%) diff --git a/docs/source/sections/Dataloaders/scalar/implemented/visual_iced.rst b/docs/source/sections/Dataloaders/scalar/implemented/visual_ice.rst similarity index 75% rename from docs/source/sections/Dataloaders/scalar/implemented/visual_iced.rst rename to docs/source/sections/Dataloaders/scalar/implemented/visual_ice.rst index 9dc7b0b2..4d87579b 100644 --- a/docs/source/sections/Dataloaders/scalar/implemented/visual_iced.rst +++ b/docs/source/sections/Dataloaders/scalar/implemented/visual_ice.rst @@ -3,13 +3,13 @@ Visual_ice Dataloader ************************* Visual_ice is a dataloader for .tiff images generated from the visual_ice library, -developed my Martin Rodgers at the British Antarctic Surveys AI Lab. The Visual_iced +developed my Martin Rogers at the British Antarctic Survey's AI Lab. The Visual_iced images are ice/water binary files, generated from a combination of MODIS and SAR -satelite imagery. +satellite imagery. In the source data, 0's are representaive of open water, and 1's are representative of ice. In the dataloader, we map theses values to Sea ice concentration, in range of 0 to 100. -Values between 0 and 100 are achived by the aggregation of the 0's and 1's which each cell. +Values between 0 and 100 are generated by the aggregation of the 0's and 1's within each cell. .. automodule:: meshiphi.dataloaders.scalar.visual_ice :special-members: __init__ From 97f817355a88c7b4a389b659d1128ff07a1ca2ef Mon Sep 17 00:00:00 2001 From: Samuel Hall <96304883+SamuelHall700@users.noreply.github.com> Date: Tue, 13 Feb 2024 14:51:42 +0000 Subject: [PATCH 15/39] updating name of dataloader to visual_iced --- .../scalar/implemented/{visual_ice.rst => visual_iced.rst} | 6 +++--- meshiphi/dataloaders/factory.py | 4 ++-- .../dataloaders/scalar/{visual_ice.py => visual_iced.py} | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) rename docs/source/sections/Dataloaders/scalar/implemented/{visual_ice.rst => visual_iced.rst} (77%) rename meshiphi/dataloaders/scalar/{visual_ice.py => visual_iced.py} (98%) diff --git a/docs/source/sections/Dataloaders/scalar/implemented/visual_ice.rst b/docs/source/sections/Dataloaders/scalar/implemented/visual_iced.rst similarity index 77% rename from docs/source/sections/Dataloaders/scalar/implemented/visual_ice.rst rename to docs/source/sections/Dataloaders/scalar/implemented/visual_iced.rst index 4d87579b..425f9f88 100644 --- a/docs/source/sections/Dataloaders/scalar/implemented/visual_ice.rst +++ b/docs/source/sections/Dataloaders/scalar/implemented/visual_iced.rst @@ -1,8 +1,8 @@ ************************* -Visual_ice Dataloader +Visual_iced Dataloader ************************* -Visual_ice is a dataloader for .tiff images generated from the visual_ice library, +Visual_iced is a dataloader for .tiff images generated from the visual_ice library, developed my Martin Rogers at the British Antarctic Survey's AI Lab. The Visual_iced images are ice/water binary files, generated from a combination of MODIS and SAR satellite imagery. @@ -11,6 +11,6 @@ In the source data, 0's are representaive of open water, and 1's are representat ice. In the dataloader, we map theses values to Sea ice concentration, in range of 0 to 100. Values between 0 and 100 are generated by the aggregation of the 0's and 1's within each cell. -.. automodule:: meshiphi.dataloaders.scalar.visual_ice +.. automodule:: meshiphi.dataloaders.scalar.visual_iced :special-members: __init__ :members: \ No newline at end of file diff --git a/meshiphi/dataloaders/factory.py b/meshiphi/dataloaders/factory.py index 17bf389d..7ba006fc 100644 --- a/meshiphi/dataloaders/factory.py +++ b/meshiphi/dataloaders/factory.py @@ -14,7 +14,7 @@ from meshiphi.dataloaders.scalar.era5_mean_wave_direction import ERA5MeanWaveDirDataLoader from meshiphi.dataloaders.scalar.era5_wind_mag import ERA5WindMagDataLoader from meshiphi.dataloaders.scalar.era5_wind_dir import ERA5WindDirDataLoader -from meshiphi.dataloaders.scalar.visual_ice import VisualIceDataLoader +from meshiphi.dataloaders.scalar.visual_iced import VisualIcedDataLoader from meshiphi.dataloaders.vector.baltic_current import BalticCurrentDataLoader from meshiphi.dataloaders.vector.era5_wind import ERA5WindDataLoader @@ -88,7 +88,7 @@ def get_dataloader(name, bounds, params, min_dp=5): 'gebco': (GEBCODataLoader, ['files']), 'icenet': (IceNetDataLoader, ['files']), 'modis': (MODISDataLoader, ['files']), - 'visual_ice': (VisualIceDataLoader, ['files']), + 'visual_iced': (VisualIcedDataLoader, ['files']), 'era5_sig_wave_height': (ERA5SigWaveHeightDataLoader, ['files']), 'era5_max_wave_height': (ERA5MaxWaveHeightDataLoader, ['files']), 'era5_wave_dir': (ERA5MeanWaveDirDataLoader, ['files']), diff --git a/meshiphi/dataloaders/scalar/visual_ice.py b/meshiphi/dataloaders/scalar/visual_iced.py similarity index 98% rename from meshiphi/dataloaders/scalar/visual_ice.py rename to meshiphi/dataloaders/scalar/visual_iced.py index 8c3b8055..c3b49b16 100644 --- a/meshiphi/dataloaders/scalar/visual_ice.py +++ b/meshiphi/dataloaders/scalar/visual_iced.py @@ -5,7 +5,7 @@ import pandas as pd -class VisualIceDataLoader(ScalarDataLoader): +class VisualIcedDataLoader(ScalarDataLoader): def import_data(self, bounds): """ Reads in data from Visual_Ice NetCDF files. Renames coordinates to From 0031cdb2f988eb9df3fcd0e498c24d536c01350e Mon Sep 17 00:00:00 2001 From: Samuel Hall <96304883+SamuelHall700@users.noreply.github.com> Date: Tue, 13 Feb 2024 15:13:37 +0000 Subject: [PATCH 16/39] removing support for multiple files in visual_iced dataloader, adding note to docs --- .../sections/Dataloaders/scalar/implemented/visual_iced.rst | 4 ++++ meshiphi/dataloaders/scalar/visual_iced.py | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/docs/source/sections/Dataloaders/scalar/implemented/visual_iced.rst b/docs/source/sections/Dataloaders/scalar/implemented/visual_iced.rst index 425f9f88..681ea28c 100644 --- a/docs/source/sections/Dataloaders/scalar/implemented/visual_iced.rst +++ b/docs/source/sections/Dataloaders/scalar/implemented/visual_iced.rst @@ -11,6 +11,10 @@ In the source data, 0's are representaive of open water, and 1's are representat ice. In the dataloader, we map theses values to Sea ice concentration, in range of 0 to 100. Values between 0 and 100 are generated by the aggregation of the 0's and 1's within each cell. +.. note:: + The Visual_iced dataload only supports loading in single files, as the visual_iced datasets + are not temporally continuous within a given boundary. + .. automodule:: meshiphi.dataloaders.scalar.visual_iced :special-members: __init__ :members: \ No newline at end of file diff --git a/meshiphi/dataloaders/scalar/visual_iced.py b/meshiphi/dataloaders/scalar/visual_iced.py index c3b49b16..dc97f5be 100644 --- a/meshiphi/dataloaders/scalar/visual_iced.py +++ b/meshiphi/dataloaders/scalar/visual_iced.py @@ -31,8 +31,8 @@ def import_data(self, bounds): logging.error('File type not supported') return None else: - visual_ice = xr.open_mfdataset(self.files) - visual_ice = self.import_from_nc(visual_ice) + logging.error('Multiple tiff files not supported. Only single tiff file supported') + return visual_ice From 42384be62e5219d853ae86cff0d5fc8d78e3926e Mon Sep 17 00:00:00 2001 From: Samuel Hall <96304883+SamuelHall700@users.noreply.github.com> Date: Tue, 13 Feb 2024 16:00:13 +0000 Subject: [PATCH 17/39] removing support for multiple files in visual_iced dataloader, adding note to docs --- .../sections/Dataloaders/scalar/implemented/visual_iced.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/source/sections/Dataloaders/scalar/implemented/visual_iced.rst b/docs/source/sections/Dataloaders/scalar/implemented/visual_iced.rst index 681ea28c..bdbc961f 100644 --- a/docs/source/sections/Dataloaders/scalar/implemented/visual_iced.rst +++ b/docs/source/sections/Dataloaders/scalar/implemented/visual_iced.rst @@ -8,11 +8,11 @@ images are ice/water binary files, generated from a combination of MODIS and SAR satellite imagery. In the source data, 0's are representaive of open water, and 1's are representative of -ice. In the dataloader, we map theses values to Sea ice concentration, in range of 0 to 100. +ice. In the dataloader, we map theses values to Sea ice concentration, in the range of 0 to 100. Values between 0 and 100 are generated by the aggregation of the 0's and 1's within each cell. .. note:: - The Visual_iced dataload only supports loading in single files, as the visual_iced datasets + The Visual_iced dataloader only supports loading in single files, as the visual_iced datasets are not temporally continuous within a given boundary. .. automodule:: meshiphi.dataloaders.scalar.visual_iced From 51a83bf15e9905ea223337adf6abb2609e6f76ea Mon Sep 17 00:00:00 2001 From: Samuel Hall <96304883+SamuelHall700@users.noreply.github.com> Date: Thu, 15 Feb 2024 11:12:29 +0000 Subject: [PATCH 18/39] initial updates to docs --- README.md | 46 +- docs/source/index.rst | 1 - .../sections/Command_line_interface.rst | 3 + .../Mesh_construction_config.rst | 440 +++++++++++------- docs/source/sections/Examples.rst | 22 - .../sections/Figures/grf_example_mesh.png | Bin 0 -> 108422 bytes .../sections/Plotting/mesh_plotting.rst | 2 + docs/source/sections/ipython_notebooks.rst | 42 +- ...tting_conf.json => png_export.config.json} | 0 .../geo.json/SIC_layer.config.json | 3 + .../export_configs/tiff/colour.config.txt | 4 + .../tiff/tiff_export.config.json | 9 + 12 files changed, 348 insertions(+), 224 deletions(-) delete mode 100644 docs/source/sections/Examples.rst create mode 100644 docs/source/sections/Figures/grf_example_mesh.png rename examples/export_configs/PNG/{plotting_conf.json => png_export.config.json} (100%) create mode 100644 examples/export_configs/geo.json/SIC_layer.config.json create mode 100644 examples/export_configs/tiff/colour.config.txt create mode 100644 examples/export_configs/tiff/tiff_export.config.json diff --git a/README.md b/README.md index 17d5ca53..0663541f 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,29 @@ +# Meshiφ (MeshiPhi) + ![](logo.jpg) - + +Manual Page + +PyPi + +Release Tag + +Issues + +License + -# Meshiφ (MeshiPhi) Introducing Meshiφ, a versatile software package designed for comprehensive earth modeling and navigation planning. Meshiφ works by discretizing the Earth's surface into a non-uniform grid, allocating higher resolution in regions of geographic diversity, and conserving lower resolution in more uniform regions. The software also incorporates data-driven vehicle models, with the ability to calculate speed limits and fuel needs for specific vessels within each grid cell. These mesh objects can be output in standard formats, such as GeoJSON and GeoTIFF, enabling data-visualisation via GIS software such as ArcGIS. ## Installation -The Meshiφ package has an optional dependance on GDAL, which is required to produce outputs in GeoJSON or GeoTIFF formats. More information on setting up GDAL can be found in the manual pages linked above. Once these requirements are met then the software can be installed by: +Meshiφ can be installed via pip or by cloning the repository from GitHub. + + Pip: +``` +pip install meshiphi +``` Github: ``` @@ -20,18 +31,10 @@ git clone https://github.com/Antarctica/MeshiPhi python setup.py install ``` - Pip: -``` -pip install meshiphi -``` +The Meshiφ package has an optional dependance on GDAL, which is required to produce outputs in GeoJSON or GeoTIFF formats. More information on setting up GDAL can be found in the manual pages linked above. Once these requirements are met then the software can be installed by: > NOTE: The installation process may vary slightly dependent on OS. Please consult the documentation for further installation guidance. -## Required Data sources -Meshiφ has been built to work with a variety of open-source atmospheric and oceanographic data sources. -A list of supported data sources and their associated data-loaders is given in the -'Data Loaders' section of the manual - ## Documentation Sphinx is used to generate documentation for this project. The dependencies can be installed through pip: ``` @@ -45,6 +48,13 @@ Sometimes the cache needs to be cleared for internal links to update. If facing ``` rm -r docs/build/.doctrees/ ``` + +## Required Data sources +Meshiφ has been built to work with a variety of open-source atmospheric and oceanographic data sources. +A list of supported data sources and their associated data-loaders is given in the +'Data Loaders' section of the manual + + ## Developers Samuel Hall, Harrison Abbot, Ayat Fekry, George Coombs, Jonathan Smith, Maria Fox, and James Byrne @@ -59,5 +69,3 @@ Jonathan D. Smith, Samuel Hall, George Coombs, James Byrne, Michael A. S. Thorne For more information please see the attached ``LICENSE`` file. -[version]: https://img.shields.io/PolarRoute/v/datadog-metrics.svg?style=flat-square -[downloads]: https://img.shields.io/PolarRoute/dm/datadog-metrics.svg?style=flat-square diff --git a/docs/source/index.rst b/docs/source/index.rst index 741a087b..31c80a0a 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -28,5 +28,4 @@ Contents: ./sections/Outputs ./sections/Dataloaders/overview ./sections/Mesh_Construction/Mesh_construction_overview - ./sections/Examples ./sections/Plotting/mesh_plotting diff --git a/docs/source/sections/Command_line_interface.rst b/docs/source/sections/Command_line_interface.rst index 4604f83f..986a40cb 100644 --- a/docs/source/sections/Command_line_interface.rst +++ b/docs/source/sections/Command_line_interface.rst @@ -21,6 +21,7 @@ positional arguments: config : A configuration file detailing how to build the digital environment. JSON parsable The format of the required ** file can be found in the :ref:`configuration - mesh construction` section of the documentation. +There are also example configuration files available in the directory :code:`examples/environment_config/grf_example.config.json` optional arguments: @@ -33,6 +34,7 @@ optional arguments: The format of the returned mesh.json file is explain in :ref:`the mesh.json file` section of the documentation. + ^^^^^^^^^^^ export_mesh ^^^^^^^^^^^ @@ -56,6 +58,7 @@ supported output formats are: * .json (default) [JSON] * geo.json (collection of polygons for each cell in the mesh) [GEOJSON] * .tif (rasterised mesh) [TIF] + * .png [PNG] optional arguments: diff --git a/docs/source/sections/Configuration/Mesh_construction_config.rst b/docs/source/sections/Configuration/Mesh_construction_config.rst index 90dde7e5..52e1772e 100644 --- a/docs/source/sections/Configuration/Mesh_construction_config.rst +++ b/docs/source/sections/Configuration/Mesh_construction_config.rst @@ -1,99 +1,217 @@ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Configuration - Mesh Construction ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Below is a full configuration file for building an environmental mesh using +data generated from gaussian random fields. This configuration file generates +the feilds 'SIC', 'elevation', 'thickness', 'density', 'uC,vC' (currents) and +'u10,v10' (winds). The full configuration file is available in the file location +:code:`examples/environment_config/grf_example.config.json`. Other example +configuration files are also available at this location, including configuration files +which build meshes using real data-sets. + + .. code-block:: json { - "Mesh_info": { - "Region": { - "latMin": -65, - "latMax": -60, - "longMin": -70, - "longMax": -50, - "startTime": "2013-03-01", - "endTime": "2013-03-14", - "cellWidth": 5, - "cellHeight": 2.5 - }, - "Data_sources": [ - { - "loader": "GEBCO", - "params": { - "downsample_factors": [ - 5, - 5 - ], - "file": "../datastore/bathymetry/GEBCO/gebco_2022_n-40.0_s-90.0_w-140.0_e0.0.nc", - "data_name": "elevation", - "value_fill_types": "parent", - "aggregate_type": "MAX", - "splitting_conditions": [ - { - "elevation": { - "threshold": -10, - "upper_bound": 1, - "lower_bound": 0 - } + "region": { + "lat_min": 0, + "lat_max": 10, + "long_min": 0, + "long_max": 10, + "start_time": "2017-02-01", + "end_time": "2017-02-04", + "cell_width": 10, + "cell_height": 10 + }, + "data_sources": [ + { + "loader": "scalar_grf", + "params": { + "data_name": "SIC", + "min": 0, + "max": 100, + "seed": 16, + "offset": 5, + "splitting_conditions": [ + { + "SIC": { + "threshold": 75, + "upper_bound": 1.0, + "lower_bound": 0.0 } - ] - } - }, - { - "loader": "AMSR", - "params": { - "folder": "../datastore/sic/amsr_south/", - "hemisphere": "south", - "value_fill_types": "parent", - "data_name": "SIC", - "splitting_conditions": [ - { - "SIC": { - "threshold": 35, - "upper_bound": 0.9, - "lower_bound": 0.1 - } - } - ] - } - }, - { - "loader": "SOSE", - "params": { - "file": "../datastore/currents/sose_currents/SOSE_surface_velocity_6yearMean_2005-2010.nc", - "value_fill_types": "parent", - "data_name": "uC,vC", - "splitting_conditions": [ - { - "uC,vC": { - "curl": 0.04 - } + } + ], + "dataloader_name": "scalar_grf", + "downsample_factors": [ + 1, + 1 + ], + "aggregate_type": "MEAN", + "min_dp": 5, + "in_proj": "EPSG:4326", + "out_proj": "EPSG:4326", + "x_col": "lat", + "y_col": "long", + "size": 512, + "alpha": 3, + "binary": false, + "threshold": [ + 0, + 1 + ], + "multiplier": 1 + } + }, + { + "loader": "scalar_grf", + "params": { + "data_name": "elevation", + "min": -100, + "max": 50, + "seed": 30, + "splitting_conditions": [ + { + "elevation": { + "threshold": -10, + "upper_bound": 1.0, + "lower_bound": 0.0 } - ] - } - }, - { - "loader": "thickness", - "params": { - "data_name": "thickness", - "file": "", - "value_fill_types": "parent" - } - }, - { - "loader": "density", - "params": { - "data_name": "density", - "file": "", - "value_fill_types": "parent" - } + } + ], + "dataloader_name": "scalar_grf", + "downsample_factors": [ + 1, + 1 + ], + "aggregate_type": "MEAN", + "min_dp": 5, + "in_proj": "EPSG:4326", + "out_proj": "EPSG:4326", + "x_col": "lat", + "y_col": "long", + "size": 512, + "alpha": 3, + "binary": false, + "threshold": [ + 0, + 1 + ], + "multiplier": 1, + "offset": 0 + } + }, + { + "loader": "scalar_grf", + "params": { + "data_name": "thickness", + "min": 0.65, + "max": 1.4, + "seed": 44, + "dataloader_name": "scalar_grf", + "downsample_factors": [ + 1, + 1 + ], + "aggregate_type": "MEAN", + "min_dp": 5, + "in_proj": "EPSG:4326", + "out_proj": "EPSG:4326", + "x_col": "lat", + "y_col": "long", + "size": 512, + "alpha": 3, + "binary": false, + "threshold": [ + 0, + 1 + ], + "multiplier": 1, + "offset": 0 + } + }, + { + "loader": "scalar_grf", + "params": { + "data_name": "density", + "min": 850, + "max": 1000, + "seed": 40, + "dataloader_name": "scalar_grf", + "downsample_factors": [ + 1, + 1 + ], + "aggregate_type": "MEAN", + "min_dp": 5, + "in_proj": "EPSG:4326", + "out_proj": "EPSG:4326", + "x_col": "lat", + "y_col": "long", + "size": 512, + "alpha": 3, + "binary": false, + "threshold": [ + 0, + 1 + ], + "multiplier": 1, + "offset": 0 + } + }, + { + "loader": "vector_grf", + "params": { + "data_name": "uC,vC", + "min": 0, + "max": 1, + "seed": 21, + "dataloader_name": "vector_grf", + "downsample_factors": [ + 1, + 1 + ], + "aggregate_type": "MEAN", + "min_dp": 5, + "in_proj": "EPSG:4326", + "out_proj": "EPSG:4326", + "x_col": "lat", + "y_col": "long", + "size": 512, + "alpha": 3, + "vec_x": "uC", + "vec_y": "vC" + } + }, + { + "loader": "vector_grf", + "params": { + "data_name": "u10,v10", + "min": 0, + "max": 1, + "seed": 21, + "dataloader_name": "vector_grf", + "downsample_factors": [ + 1, + 1 + ], + "aggregate_type": "MEAN", + "min_dp": 5, + "in_proj": "EPSG:4326", + "out_proj": "EPSG:4326", + "x_col": "lat", + "y_col": "long", + "size": 512, + "alpha": 3, + "vec_x": "uC", + "vec_y": "vC" } - ], - "splitting": { - "split_depth": 4, - "minimum_datapoints": 5 } + ], + "splitting": { + "split_depth": 6, + "minimum_datapoints": 5 } - } The configuration file used for mesh construction contains information required to build the discretised environment in which the route planner @@ -109,30 +227,30 @@ The region section gives detailed information for the construction of the Discre :: - "Region": { - "latMin": -77.5, - "latMax": -55, - "longMin": -120, - "longMax": -10, - "startTime": "2017-02-01", - "endTime": "2017-02-14", - "cellWidth":5, - "cellHeight":2.5 - } + "region": { + "lat_min": 0, + "lat_max": 10, + "long_min": 0, + "long_max": 10, + "start_time": "2017-02-01", + "end_time": "2017-02-04", + "cell_width": 10, + "cell_height": 10 + } where the variables are as follows: -* **longMin** *(float, degrees)* : Minimum Longitude Edge Mesh -* **longMax** *(float, degrees)* : Maximum Longitude Edge Mesh -* **latMin** *(float, degrees)* : Minimum Latitude Edge Mesh -* **latMax** *(float, degrees)* : Maximum Latitude Edge Mesh -* **startTime** *(string, 'YYYY-mm-dd')* : Start Datetime of Time averaging -* **endTime** *(string, 'YYYY-mm-dd')* : End Datetime of Time averaging -* **cellWidth** *(float, degrees)* : Initial Cell Box Width prior to splitting -* **cellHeight** *(float, degrees)* : Initial Cell Box Height prior to splitting +* **long_min** *(float, degrees)* : Minimum Longitude Edge Mesh +* **long_max** *(float, degrees)* : Maximum Longitude Edge Mesh +* **lat_min** *(float, degrees)* : Minimum Latitude Edge Mesh +* **lat_max** *(float, degrees)* : Maximum Latitude Edge Mesh +* **start_time** *(string, 'YYYY-mm-dd')* : Start Datetime of Time averaging +* **end_time** *(string, 'YYYY-mm-dd')* : End Datetime of Time averaging +* **cell_width** *(float, degrees)* : Initial Cell Box Width prior to splitting +* **cell_height** *(float, degrees)* : Initial Cell Box Height prior to splitting .. note:: - Variables **startTime** and **endTime** also support reference to system time using + Variables **start_time** and **end_time** also support reference to system time using the keyword **TODAY** *e.g.* "startTime": "TODAY" , "endTime": "TODAY + 5" @@ -149,79 +267,47 @@ to the mesh. :: - "Data_sources": [ - { - "loader": "GEBCO", - "params": { - "downsample_factors": [ - 5, - 5 - ], - "file": "../datastore/bathymetry/GEBCO/gebco_2022_n-40.0_s-90.0_w-140.0_e0.0.nc", - "data_name": "elevation", - "value_fill_types": "parent", - "aggregate_type": "MAX", - "splitting_conditions": [ - { - "elevation": { - "threshold": -10, - "upper_bound": 1, - "lower_bound": 0 - } - } - ] + "data_sources": [ + { + "loader": "scalar_grf", + "params": { + "data_name": "SIC", + "min": 0, + "max": 100, + "seed": 16, + "offset": 5, + "splitting_conditions": [ + { + "SIC": { + "threshold": 75, + "upper_bound": 1.0, + "lower_bound": 0.0 + } } - }, - { - "loader": "AMSR", - "params": { - "folder": "../datastore/sic/amsr_south/", - "hemisphere": "south", - "value_fill_types": "parent", - "data_name": "SIC", - "splitting_conditions": [ - { - "SIC": { - "threshold": 35, - "upper_bound": 0.9, - "lower_bound": 0.1 - } - } - ] - } - }, - { - "loader": "SOSE", - "params": { - "file": "../datastore/currents/sose_currents/SOSE_surface_velocity_6yearMean_2005-2010.nc", - "value_fill_types": "parent", - "data_name": "uC,vC", - "splitting_conditions": [ - { - "uC,vC": { - "curl": 0.04 - } - } - ] - } - }, - { - "loader": "thickness", - "params": { - "data_name": "thickness", - "file": "", - "value_fill_types": "parent" - } - }, - { - "loader": "density", - "params": { - "data_name": "density", - "file": "", - "value_fill_types": "parent" - } - } - ] + ], + "dataloader_name": "scalar_grf", + "downsample_factors": [ + 1, + 1 + ], + "aggregate_type": "MEAN", + "min_dp": 5, + "in_proj": "EPSG:4326", + "out_proj": "EPSG:4326", + "x_col": "lat", + "y_col": "long", + "size": 512, + "alpha": 3, + "binary": false, + "threshold": [ + 0, + 1 + ], + "multiplier": 1 + } + }, + ... other data_sources + ] where the variables are as follows: @@ -298,7 +384,7 @@ of non-uniform spatial resolution. :: "splitting": { - "split_depth":4, + "split_depth":6, "minimum_datapoints":5 } diff --git a/docs/source/sections/Examples.rst b/docs/source/sections/Examples.rst deleted file mode 100644 index 752e6ea4..00000000 --- a/docs/source/sections/Examples.rst +++ /dev/null @@ -1,22 +0,0 @@ -************************ -Examples of running code -************************ -Throughout this section we will discuss a series of examples that can be run by the user either from the Command-Line or within python/ipython notebooks. All these examples and more can be found at the Google Colab `Link `_. - -============================================================= -Example 1 - Antarctica Processing all stages of route planner -============================================================= - -In this section we will outline the full processing procedures for running PolarRoute ...to be added shortly ... - - -==================================== -Example 2 - Dijkstra vs smooth paths -==================================== -...to be added shortly ... - - -============================================================ -Example 2 - Variations of Vehicle Properties on Route Paths -============================================================ -...to be added shortly ... \ No newline at end of file diff --git a/docs/source/sections/Figures/grf_example_mesh.png b/docs/source/sections/Figures/grf_example_mesh.png new file mode 100644 index 0000000000000000000000000000000000000000..e54eab2f19017981827b340f781f2c37817bdfce GIT binary patch literal 108422 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 Date: Thu, 15 Feb 2024 11:16:11 +0000 Subject: [PATCH 19/39] initial updates to docs --- docs/source/sections/Command_line_interface.rst | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/docs/source/sections/Command_line_interface.rst b/docs/source/sections/Command_line_interface.rst index 986a40cb..f385de00 100644 --- a/docs/source/sections/Command_line_interface.rst +++ b/docs/source/sections/Command_line_interface.rst @@ -120,10 +120,21 @@ optional arguments: -o : output location -^^^^^^^^ -Plotting -^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^ +plot_mesh (GeoPlot) +^^^^^^^^^^^^^^^^^^^^^ Meshes produced at any stage in the route planning process can be visualised using the GeoPlot library found at the relevant `GitHub page `_. Meshes and routes can also be plotted in other GIS software such as QGIS by exporting the mesh to a common format such as .geojson or .tif using the :ref:`export_mesh` command. + +:: + + plot_mesh + +optional arguments: + +:: + + -v : verbose logging + -o : output location From 59d022c3b5ae51d938ce3f32d5a8b4ba79e0a0e9 Mon Sep 17 00:00:00 2001 From: Samuel Hall <96304883+SamuelHall700@users.noreply.github.com> Date: Thu, 15 Feb 2024 11:21:19 +0000 Subject: [PATCH 20/39] renaming of PolarRoute to MeshiPhi in installsation --- docs/source/sections/Installation.rst | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/docs/source/sections/Installation.rst b/docs/source/sections/Installation.rst index b1f20ca1..9cfac652 100644 --- a/docs/source/sections/Installation.rst +++ b/docs/source/sections/Installation.rst @@ -6,27 +6,28 @@ In this section we will outline the installation steps for installing the softwa The first stage is installing a version of Python 3.9, if you don't have a working version. We suggest installing a working Anaconda distribution from https://www.anaconda.com/products/distribution#macos following the instructions on that page. -Installing PolarRoute +Installing MeshiPhi ##################### -The PolarRoute software can be installed on Windows/Linux/MacOS by running one of the two following commands. +The MeshiPhi software can be installed on Windows/Linux/MacOS by running one of the two following commands. -Github: + +Pip: :: - git clone https://https://github.com/antarctica/PolarRoute.git - python setup.py install + pip install MeshiPhi -Pip: +Github: :: - pip install polar-route + git clone https://https://github.com/antarctica/MeshiPhi.git + python setup.py install Installing GDAL ############### -The PolarRoute software has GDAL as an optional requirement. It is only used when exporting TIFF images, +The MeshiPhi software has GDAL as an optional requirement. It is only used when exporting TIFF images, so if this is not useful to you, we would recommend steering clear. It is not trivial and is a common source of problems. With that said, below are instructions for various operating systems. @@ -35,7 +36,7 @@ Windows .. note:: We assume a version of Windows 10 or higher, with a working version of Python 3.9 including pip installed. - We recommend installing PolarRoute into a virtual environment. + We recommend installing MeshiPhi into a virtual environment. Windows: From 5a1ca0e465a4ef3e977d6829417a2f327e9bd0f3 Mon Sep 17 00:00:00 2001 From: Samuel Hall <96304883+SamuelHall700@users.noreply.github.com> Date: Thu, 15 Feb 2024 11:24:04 +0000 Subject: [PATCH 21/39] removing test message --- docs/source/sections/Plotting/mesh_plotting.rst | 2 -- 1 file changed, 2 deletions(-) diff --git a/docs/source/sections/Plotting/mesh_plotting.rst b/docs/source/sections/Plotting/mesh_plotting.rst index 59094064..f3c72d22 100644 --- a/docs/source/sections/Plotting/mesh_plotting.rst +++ b/docs/source/sections/Plotting/mesh_plotting.rst @@ -2,8 +2,6 @@ Mesh Plotting ############################ -test test - .. automodule:: meshiphi.mesh_plotting.mesh_plotter :special-members: __init__ :members: \ No newline at end of file From 5086d0fe11ad3bbd18316ac1228ac9e930a689b6 Mon Sep 17 00:00:00 2001 From: Samuel Hall <96304883+SamuelHall700@users.noreply.github.com> Date: Thu, 15 Feb 2024 15:17:36 +0000 Subject: [PATCH 22/39] updating setup.py install with pip install . --- README.md | 5 +++-- docs/source/sections/Installation.rst | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 0663541f..e373a204 100644 --- a/README.md +++ b/README.md @@ -25,10 +25,11 @@ Meshiφ can be installed via pip or by cloning the repository from GitHub. pip install meshiphi ``` -Github: +Github: (for local development) ``` git clone https://github.com/Antarctica/MeshiPhi -python setup.py install +cd MeshiPhi +pip install -e . ``` The Meshiφ package has an optional dependance on GDAL, which is required to produce outputs in GeoJSON or GeoTIFF formats. More information on setting up GDAL can be found in the manual pages linked above. Once these requirements are met then the software can be installed by: diff --git a/docs/source/sections/Installation.rst b/docs/source/sections/Installation.rst index 9cfac652..94dd12b5 100644 --- a/docs/source/sections/Installation.rst +++ b/docs/source/sections/Installation.rst @@ -20,8 +20,9 @@ Pip: Github: :: - git clone https://https://github.com/antarctica/MeshiPhi.git - python setup.py install + git clone https://github.com/antarctica/MeshiPhi.git + cd MeshiPhi + pip install . Installing GDAL From 536716c05870d7197eddc05dc3a7d27c39ed6d80 Mon Sep 17 00:00:00 2001 From: Samuel Hall <96304883+SamuelHall700@users.noreply.github.com> Date: Thu, 15 Feb 2024 15:52:45 +0000 Subject: [PATCH 23/39] renaming examples folder --- docs/source/index.rst | 2 +- docs/source/sections/ipython_notebooks.rst | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/source/index.rst b/docs/source/index.rst index 31c80a0a..c8b99f33 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -20,10 +20,10 @@ Contents: :maxdepth: 2 :numbered: - ./sections/Code_overview ./sections/Installation ./sections/ipython_notebooks ./sections/Command_line_interface + ./sections/Code_overview ./sections/Configuration/Configuration_overview ./sections/Outputs ./sections/Dataloaders/overview diff --git a/docs/source/sections/ipython_notebooks.rst b/docs/source/sections/ipython_notebooks.rst index 8979989a..1c31d781 100644 --- a/docs/source/sections/ipython_notebooks.rst +++ b/docs/source/sections/ipython_notebooks.rst @@ -1,6 +1,6 @@ -############################### -Python & iPython Notebooks -############################### +##################################### +Python & iPython Notebooks examples +##################################### Route planning may also be done using a python terminal. This is case, the CLI is not required but the steps required for route planning follow the same format - create a digital environment; simulated a vessel against it; optimise a route plan through the digital environment. From 901f3f291a0ceaa2dfc886aa6efb6d2a54fea2d5 Mon Sep 17 00:00:00 2001 From: Samuel Hall <96304883+SamuelHall700@users.noreply.github.com> Date: Fri, 16 Feb 2024 09:51:07 +0000 Subject: [PATCH 24/39] updating reference to CartograPhi in command line interface section --- docs/source/sections/Command_line_interface.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/source/sections/Command_line_interface.rst b/docs/source/sections/Command_line_interface.rst index f385de00..8d440f0f 100644 --- a/docs/source/sections/Command_line_interface.rst +++ b/docs/source/sections/Command_line_interface.rst @@ -2,8 +2,9 @@ Command Line Interface ############################### -The CaartograPhi package provides CLI entry points, intended to be used in succession to plan a route through a digital environment. - +The MeshiPhi package provides CLI entry points, used to build a digital environment from a hetrogeneous collection of source data. +This digital environment file (mesh) may then be exported to a variety of file formats for use in other systems, such as GIS software. +The produced mesh file also interfaces directly with PolarRoute, BAS's route planning software to provide optinal routes through mesh. ^^^^^^^^^^^ create_mesh ^^^^^^^^^^^ From c7c44de1c9733823182778fb873bb0d8a42d8c34 Mon Sep 17 00:00:00 2001 From: George Date: Fri, 16 Feb 2024 13:29:14 +0000 Subject: [PATCH 25/39] Docs typos --- .../scalar/implemented/visual_iced.rst | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/source/sections/Dataloaders/scalar/implemented/visual_iced.rst b/docs/source/sections/Dataloaders/scalar/implemented/visual_iced.rst index bdbc961f..7f910ed3 100644 --- a/docs/source/sections/Dataloaders/scalar/implemented/visual_iced.rst +++ b/docs/source/sections/Dataloaders/scalar/implemented/visual_iced.rst @@ -2,19 +2,19 @@ Visual_iced Dataloader ************************* -Visual_iced is a dataloader for .tiff images generated from the visual_ice library, -developed my Martin Rogers at the British Antarctic Survey's AI Lab. The Visual_iced -images are ice/water binary files, generated from a combination of MODIS and SAR +Visual_iced is a dataloader for .tiff images, which are outputs from the visual_iced library +developed by Martin Rogers at the British Antarctic Survey's AI Lab. These visual_iced +images are ice/water binary files, generated from a combination of MODIS and SAR satellite imagery. -In the source data, 0's are representaive of open water, and 1's are representative of -ice. In the dataloader, we map theses values to Sea ice concentration, in the range of 0 to 100. -Values between 0 and 100 are generated by the aggregation of the 0's and 1's within each cell. +In the source data, 0s are representative of open water, and 1s are representative of +ice. In the dataloader, we map these values to sea ice concentration, in the range of 0 to 100. +Values between 0 and 100 are generated by the aggregation of the 0s and 1s within each cell. .. note:: - The Visual_iced dataloader only supports loading in single files, as the visual_iced datasets + The visual_iced dataloader only supports loading in single files, as the visual_iced datasets are not temporally continuous within a given boundary. .. automodule:: meshiphi.dataloaders.scalar.visual_iced :special-members: __init__ - :members: \ No newline at end of file + :members: From f682635f3de4a73dd14d534809be9e18d9061656 Mon Sep 17 00:00:00 2001 From: Samuel Hall <96304883+SamuelHall700@users.noreply.github.com> Date: Fri, 16 Feb 2024 13:44:26 +0000 Subject: [PATCH 26/39] Updating reference to route planning in the python examples page of the docs --- docs/source/sections/ipython_notebooks.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/source/sections/ipython_notebooks.rst b/docs/source/sections/ipython_notebooks.rst index 1c31d781..8a868de3 100644 --- a/docs/source/sections/ipython_notebooks.rst +++ b/docs/source/sections/ipython_notebooks.rst @@ -2,8 +2,9 @@ Python & iPython Notebooks examples ##################################### -Route planning may also be done using a python terminal. This is case, the CLI is not required but the steps required for route planning -follow the same format - create a digital environment; simulated a vessel against it; optimise a route plan through the digital environment. +Digital environement files (meshes) can be created using the MeshiPhi package, either through the +command line interface (CLI) or through the python terminal. This section will provide examples of how to create a digital +environement file using the python terminal. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ From e98ce0773fc8f51ca68dc78ce4faaac04e0b6c50 Mon Sep 17 00:00:00 2001 From: Samuel Hall <96304883+SamuelHall700@users.noreply.github.com> Date: Fri, 16 Feb 2024 13:45:27 +0000 Subject: [PATCH 27/39] renaming python and ipython notebook examples to just Examples --- docs/source/sections/ipython_notebooks.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/sections/ipython_notebooks.rst b/docs/source/sections/ipython_notebooks.rst index 8a868de3..c1e8fcff 100644 --- a/docs/source/sections/ipython_notebooks.rst +++ b/docs/source/sections/ipython_notebooks.rst @@ -1,5 +1,5 @@ ##################################### -Python & iPython Notebooks examples +Examples ##################################### Digital environement files (meshes) can be created using the MeshiPhi package, either through the From e926dc687d2b6dac01e4d2bb991632e441397f59 Mon Sep 17 00:00:00 2001 From: Samuel Hall <96304883+SamuelHall700@users.noreply.github.com> Date: Fri, 16 Feb 2024 14:43:19 +0000 Subject: [PATCH 28/39] added error thrown when multiple .tiff files and used --- meshiphi/dataloaders/scalar/visual_iced.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meshiphi/dataloaders/scalar/visual_iced.py b/meshiphi/dataloaders/scalar/visual_iced.py index dc97f5be..23d48793 100644 --- a/meshiphi/dataloaders/scalar/visual_iced.py +++ b/meshiphi/dataloaders/scalar/visual_iced.py @@ -32,7 +32,7 @@ def import_data(self, bounds): return None else: logging.error('Multiple tiff files not supported. Only single tiff file supported') - + raise ValueError('Multiple tiff files not supported. Only single tiff file supported') return visual_ice From b58b0fdc276de4771c8b1f7fad675cbc13b999ca Mon Sep 17 00:00:00 2001 From: Samuel Hall <96304883+SamuelHall700@users.noreply.github.com> Date: Fri, 16 Feb 2024 14:51:58 +0000 Subject: [PATCH 29/39] rebuilding docs before merge into main --- docs/html/.doctrees/environment.pickle | Bin 363562 -> 467309 bytes docs/html/.doctrees/index.doctree | Bin 6877 -> 6849 bytes .../sections/Dataloaders/Factory.doctree | Bin 23267 -> 23763 bytes .../Dataloaders/scalar/abstractScalar.doctree | Bin 77994 -> 79730 bytes .../scalar/implemented/AMSR.doctree | Bin 15054 -> 15488 bytes .../scalar/implemented/BSOSEDepth.doctree | Bin 12332 -> 12642 bytes .../scalar/implemented/BSOSESeaIce.doctree | Bin 13012 -> 13322 bytes .../scalar/implemented/BalticSeaIce.doctree | Bin 11355 -> 11665 bytes .../scalar/implemented/GEBCO.doctree | Bin 9953 -> 10263 bytes .../scalar/implemented/IceNet.doctree | Bin 11451 -> 11761 bytes .../scalar/implemented/MODIS.doctree | Bin 10941 -> 11251 bytes .../scalar/implemented/ScalarCSV.doctree | Bin 9861 -> 10171 bytes .../scalar/implemented/ScalarGRF.doctree | Bin 19218 -> 19652 bytes .../scalar/implemented/Shape.doctree | Bin 19727 -> 20533 bytes .../sections/Dataloaders/scalar/index.doctree | Bin 11319 -> 11450 bytes .../Dataloaders/vector/abstractVector.doctree | Bin 116859 -> 119463 bytes .../vector/implemented/BalticCurrent.doctree | Bin 12156 -> 12466 bytes .../vector/implemented/ERA5Wind.doctree | Bin 11838 -> 12148 bytes .../implemented/NorthSeaCurrent.doctree | Bin 10773 -> 11083 bytes .../vector/implemented/ORAS5Current.doctree | Bin 11877 -> 12187 bytes .../vector/implemented/SOSE.doctree | Bin 11873 -> 12183 bytes .../vector/implemented/VectorCSV.doctree | Bin 9861 -> 10171 bytes .../vector/implemented/VectorGRF.doctree | Bin 18263 -> 18697 bytes .../.doctrees/sections/Installation.doctree | Bin 9770 -> 9726 bytes docs/html/_sources/index.rst.txt | 3 +- .../_sources/sections/Installation.rst.txt | 20 +++--- docs/html/genindex.html | 45 ++----------- docs/html/index.html | 48 ++++++-------- docs/html/objects.inv | Bin 5539 -> 5347 bytes docs/html/py-modindex.html | 16 ++--- docs/html/search.html | 11 ++-- docs/html/searchindex.js | 2 +- docs/html/sections/Dataloaders/Factory.html | 10 +-- docs/html/sections/Dataloaders/overview.html | 10 +-- .../Dataloaders/scalar/abstractScalar.html | 10 +-- .../Dataloaders/scalar/implemented/AMSR.html | 36 +++++----- .../scalar/implemented/BSOSEDepth.html | 36 +++++----- .../scalar/implemented/BSOSESeaIce.html | 36 +++++----- .../scalar/implemented/BalticSeaIce.html | 36 +++++----- .../scalar/implemented/BinaryGRF.html | 40 +++++------ .../Dataloaders/scalar/implemented/GEBCO.html | 50 +++++++------- .../scalar/implemented/IceNet.html | 50 +++++++------- .../Dataloaders/scalar/implemented/MODIS.html | 50 +++++++------- .../scalar/implemented/ScalarCSV.html | 50 +++++++------- .../scalar/implemented/ScalarGRF.html | 50 +++++++------- .../Dataloaders/scalar/implemented/Shape.html | 50 +++++++------- .../sections/Dataloaders/scalar/index.html | 62 ++++++++++-------- .../Dataloaders/vector/abstractVector.html | 10 +-- .../vector/implemented/BalticCurrent.html | 10 +-- .../vector/implemented/ERA5Wind.html | 10 +-- .../vector/implemented/NorthSeaCurrent.html | 10 +-- .../vector/implemented/ORAS5Current.html | 10 +-- .../Dataloaders/vector/implemented/SOSE.html | 10 +-- .../vector/implemented/VectorCSV.html | 10 +-- .../vector/implemented/VectorGRF.html | 10 +-- .../sections/Dataloaders/vector/index.html | 14 ++-- docs/html/sections/Installation.html | 59 +++++++++-------- docs/html/sections/Outputs.html | 10 +-- 58 files changed, 433 insertions(+), 451 deletions(-) diff --git a/docs/html/.doctrees/environment.pickle b/docs/html/.doctrees/environment.pickle index a6f7c39395512175f98939584fd86020ebc02e8f..368262be324eb65eb5f351f5941f691e8b83f8d3 100644 GIT binary patch literal 467309 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 J6X~9w_V|g=x&0=^k!0^sF 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 diff --git a/docs/html/.doctrees/index.doctree b/docs/html/.doctrees/index.doctree index f5d2f037a9468ac5fa4b95d97faed30fe60d5353..a94a5ea697cedaea456b6a70968fb546bfb150c3 100644 GIT binary patch delta 77 zcmca>deD@mfpzM(jVvhwlUoE5CT9r9OnxG;eDWf}Wb1cCC diff --git a/docs/html/.doctrees/sections/Dataloaders/Factory.doctree b/docs/html/.doctrees/sections/Dataloaders/Factory.doctree index 93636701562ffe64b445cdeefdda323c3f743baa..d84e6722504b1ade8a43ecf704d2da248126031c 100644 GIT binary patch delta 916 zcmaF7mGSaUM%D(_sV8DKvbxKp9&omb2`x@7Dvl{m%*{y5$%%0+C~!$ENsRHyPfpB< z2`I`>FG|cUjtQtN$;i)xQpSb`F*%t@F~ylBsk#M;$=QkNsl_q5sl^$Y1sR#ThI)p2 zrn&`{#(IVZda3E@ljD>VH(!zQXQHEZtL1x`>0{mIIOVHMspshwkTH{cR0KC4SKGrz qXDh|^I3-fA(#@A2TtqkTaGS|YXDeTNvGJy^qmwVaHYY?hGXVf@vQy*$ delta 420 zcmcb-lkxFZM%D(_sW+lFvbxKtHzixeloqEJ6~`1O=4K@3PIFpG*ROEU8Fpp>zpK}=3&QcQ7XNvdu^Vsdt3dTMb@ZfbExWxZO|IwV*u0l-12dhi z6ce_WP5nSOU;62bZ00f)XQs22*G&F%(b38TSMklg4n{2WvvPBSYc+rB3p&MP=jQIv zc`Wp?ZgW7?G49m&bn;o%qzNpO`_uU*U&v(Hd^RnBiS9OUzL1&ANncy%)(CC>Qq00Z zS6esFt;rCer;S3Jck~7@)7Qq`6R)VGKBrgO-E6RZ2P^%on{2S1Z}arMuS8N`(#waF zb1rgk*1c@WOlK>FuD1))Ctx=pcoD-%AFC!Gc+s)>^rv;~oKxe>8Ngt&++V}Zt9~W2 zPIj=6-D=1f%}&4kvR#*h5!j}rTS>p&mYeYnSL$1Oq}}ZSVvHiJ^s#F?(5}Aik}`}; Tf~jZd;W=P`AY=I|T}EaA++(iR delta 1474 zcmezLj%C$DmJK@0>hqJWVoHlsi;8246LT{Xb8=#e^Gl18Q)7x!3-XI&a#M>lG7B;? zH&0}K!9=X$$rG6yH^;MIWFbLA-DY9l-Hhrhh;z>5gY{LL*YfXRCPl;KwfwxB14XQ4 z)i)7u%j5?JLYr%hB$-Lp)Mm!WO_HWQck#`&PDU)GXxiN8Ud^w*iUj{8L~(Ea9KMK! zWKH$4j@;@SiMFYJ^2;2-$=}0yHy_G$W+Fx7=9f8DoFr(NusNcfg@afPn-A7M6ChSG zFrC#+K0Q@v^PGu3%%o`Ae0u6574?-whgRL@3A?wjlA>Yqgxy@54G+B%QD058Emf2M z-Q?NKcEf_1WKEiP+5|~(Ue#p(AAFnVyt~3dil)u}KlZRszR=7y{T(YK+w_x6jEY-b z853DKr%p3q0E5Yjx23lqWMzzHCpI>wUld@R07{4375Er^h)#&xf!flz)z=drw$uBS h7)7>g$uhRFkfLonP@9;bdLNM%O=QkkUSz_^3;@4HW^e!i diff --git a/docs/html/.doctrees/sections/Dataloaders/scalar/implemented/AMSR.doctree b/docs/html/.doctrees/sections/Dataloaders/scalar/implemented/AMSR.doctree index 01371140f5796064495c5ddfd8874d973812a051..2c6037fb475218a580dcadd889df0001a8b7fe37 100644 GIT binary patch delta 798 zcmX?C+EB^bz&f?mW+ST|SL!xrtC-N@)S}{;;>6sH#GITM$ASWv#FE4qpZw&+oS1;3 z{Pd#4+~Syk%94!yJSb&sXb_W=nG{o;S(2(-keHmEn4Vf3lbc$cky((DscWcbsAsBM zP-(1ZXrPyxo<6yTJ81GAu9>Mv>0#UE8tyGj^sx%)vCPc}`2Mh_-k^uifYv2W4wsbJ k93xuHOg}3(hf5yiO1(%oA6l#NZr-S3$4qA{TQt0c0I(e6sH#GIU%;{4L0_M@Vl`|Q$u!GbyGxvm{lwATc>RF+H_7CO5S>BeNhQQ`b<>P|sAi zpwd{+&_FLWJ$>?hiG;~Qd<#-<(#f{c$q7Ono5T3?nCNHa<^-V#w$!Ke@ZskB5?h(+ PV-+y!+BQ4Nz7_%iFUixd delta 254 zcmaEqv?hVIfpw~)!A90LUiG$QtC-T_)S}{;;>6sH#GIU%;{4L0QRXW=X1UL1J=tVtQ(EOm1p%MrJ`qrmmr$p`NL3 zL8Y;tp@Cj%divx9iImBOyo*xr(aE-|&0F|tndoTUCBbyI)K~QI-R1;|t<3bX3K(tO Kn~%%ziU9!kvC=32 delta 178 zcmeCmxRT1+z&iD$(MHyXJgi;GRxzcMvl*p0a#M>lG7B;?H+%E4F|sbe5TESLn=<(w szr^G|A-2sH{H08I)NJk(N@ZhRgUbxD$#2E^Hb0QmWhSKNm#lyo0OK=13IG5A diff --git a/docs/html/.doctrees/sections/Dataloaders/scalar/implemented/BalticSeaIce.doctree b/docs/html/.doctrees/sections/Dataloaders/scalar/implemented/BalticSeaIce.doctree index 27e9f1e2ca252742e4be69da69c0c942eff40120..cc24a919e906a6cf2c3ec2cfe0d7e94c48fec11f 100644 GIT binary patch delta 569 zcmcZ|F)^C8fpuz|?nc(5oT;artztrpQ;UjYiW74)5_5859199u5=#QRXW=X1UL1J=tVtQ(EOm1p%MrJ`qrmmr$p`NL3 zL8Y;tp@Cj%div&%oSclQ59wl+BKIFA`dBqtk-K&CNj?>})VK8T8PK}g$pIofo9BwE MFw@z}LdjP`0QnKo1^@s6 delta 174 zcmbOjeLI4+fpuzt&PLXwoUA>`RxzcMa~Y*La#M>lG7B;?H|uk8GO{kl5TC5il{Wb{ nkK|?{X=@*}@FTuNcnwT;(AvG(cUJ3yK0xdeC diff --git a/docs/html/.doctrees/sections/Dataloaders/scalar/implemented/GEBCO.doctree b/docs/html/.doctrees/sections/Dataloaders/scalar/implemented/GEBCO.doctree index ce7c16da8067260e8bbb98667d74e014c114b999..ff1e2708735d8f56d3463334e6b8fb0da0fddd8f 100644 GIT binary patch delta 572 zcmaFpJ3WB4fpsd6#zxlvtf@PktztrpQ;UjYiW74)5_5859199u5=#QRXW=X1UL1J=tVtQ(EOm1p%MrJ`qrmmr$p`NL3 zL8Y;tp@Cj%dirDs_K?Z-Y_n2N(8IRP4(xlF=wlVoV>z4qxz@6#UZIE2fYzl<_T%T< Qd{tl#6P>M;5;-me0H77o!T9%sb;QYo7i lI3k#E$W2z@;MnZRy_S`A8aBP9n=c5iWWpl1`JRZSFaXi$H(~$) diff --git a/docs/html/.doctrees/sections/Dataloaders/scalar/implemented/IceNet.doctree b/docs/html/.doctrees/sections/Dataloaders/scalar/implemented/IceNet.doctree index a2a3a76ceeb5a8a828a3fde3d71bb616dbc235be..3b838950aef8e4e6609064c528c7a85891c4ae10 100644 GIT binary patch delta 568 zcmdlT`7xTcfpzLL-Hoi4+^M^qtztrpQ;UjYiW74)5_5859199u5=#QRXW=X1UL1J=tVtQ(EOm1p%MrJ`qrmmr$p`NL3 zL8Y;tp@Cj%divxB$*{@0xo4-Irju>ylh5;WY<|NN%0xdaH=pN!#+rJaPCl&I93sZb NOdsnuH%M9w0|0=K(%b+5 delta 153 zcmewuy*rY%fpzKzosF!P+^jXpRxzcMV;QA5a#M>lG7B;?C;#LLoBWe|Hft}2)aIW& pN0_jP1GVIDo+xmSm31bD9-v(MWLas!%|7C+%sAvX%SvAn0ss}xI1~T? diff --git a/docs/html/.doctrees/sections/Dataloaders/scalar/implemented/MODIS.doctree b/docs/html/.doctrees/sections/Dataloaders/scalar/implemented/MODIS.doctree index f53ee582d25cc9fd16c9c578f1c696be57da149c..cdf0c73ffebc129b407b5ac53af517495f768ead 100644 GIT binary patch delta 564 zcmdlR`Z=7nfpzK&?TxI3oT)pUtztrpQ;UjYiW74)5_5859199u5=#QRXW=X1UL1J=tVtQ(EOm1p%MrJ`qrmmr$p`NL3 zL8Y;tp@Cj%dirEXk&wwBIcKGwpp$JWo5i>znCNKTPhLf~)GPGx-DXD-d1m@p1&p@R K&40uX3IPBq>d-R) delta 153 zcmewyzBiP$fpzL8t&OaOoUB#JRxzcMqZy?*a#M>lG7B;?C;Rh-OxEX`#oC2UDrfU7 l?f@n%a-046TG?2qVbhbcd9LVgCLD5;=ZXq$Hj+Fj1OW2>G{pb_ diff --git a/docs/html/.doctrees/sections/Dataloaders/scalar/implemented/ScalarCSV.doctree b/docs/html/.doctrees/sections/Dataloaders/scalar/implemented/ScalarCSV.doctree index 3944373b84c0778f4833a03df63f8988e91d3c2e..f1a484b50d52ee76a4ac6c6038cd8c6312c31fc4 100644 GIT binary patch delta 572 zcmZqm-R;lXz&dq<`bJg-*3?7JRxzQ)sYS&x#fiBYi8(njjs*oSi6x0KKKaRsIWYl6 z`RPT8xy3O7l_eSZc~HvO&>$u!GbyGxvm{lwATc>RF+H_7CO5S>BeNhQQ`b<>P|sAi zpwd{+&_FLWJ$-TkTioPTtn*W^(ZjaQ1#AzP=wlVoV^y0!a$aOjeMAqR0j(>Ve1VT| QbEbd?6P>M$5Y`n20MDS)TmS$7 delta 250 zcmdn(-|EZSz&f=`Z6m7!t9nbaRZMAdYEf}aabj*pVopv>aeir0a%xObYC(Q+Om1p% zMrJ`q=43;zxXCYA=c~^kT7A{#H1;$mVl`|wFG|cUjtQtN$;i)xQpSb`F*%t@F~ylBsk#M;$=QkNsl_q5sl^$Y1sR#ThI)p2 zrn&`{#(IVZda3E@n-j#C8B?#(!>Y*%VsVr06+|}w5ie$F7(%%_>TN jnCNWfIn`O*sgLOBOVP<@rUILVjJlZUYwcz;(>tO7cAP3E delta 370 zcmX>ylX22CM%D(_sqEexSxv;$Tav9}N{dsAierisb2Acia$<_}ON)|IV~SD>@{40~ zQ;Rb)3ov6mQIL(Abe)9!kQ*PGT*z~1N(qNtZK#q6vL-}j? zRcxNDn8wOF6^9{Qlh3Lj!!5fxT@$EzIu6Y&llL2OPF|va8o!FoZicFCtkWkmKQSb@mN+3(icRd{@q9^DVh%rpb(Q+T3NC z#ifZk@tMh~DU+iVbUCj}x3K|~&qDDC0QOUz9zsVqn>o>DtSBMYRl1FWwzV^b$sOD9-)XK98I zP(g-lh8n~~wT$%{)?ni@wt~&dQUDvso0gxy`HAKNMkZdS$^WF~COa^(uoh=1WN}Si NtL@LoG5N2y6#&u;Nmc*= delta 205 zcmdlLxjllVfpx0RMwXRwlb^}!ZkCd7W}19WF?zGLQXL~>+2&o!4or*-Hvd+A%UoZ^ z$iR>xn^g*=vWh_LO&RO6WI;SB5RnTavVcTs4`*ItZfZ$oL2B`o+9?`YAdMYheVrMb zI>A~x!OA;JGlYN&GGsHGNIGHB@la`z8 Xz{J8@oS~4#HrYVOpOIy9gN_vdSA9Ed diff --git a/docs/html/.doctrees/sections/Dataloaders/vector/abstractVector.doctree b/docs/html/.doctrees/sections/Dataloaders/vector/abstractVector.doctree index 450b68f67fc4137dd955a19b184a5ffa69f8cb77..8cd6b24f7371f0a2a75015e0ea607f488d23031b 100644 GIT binary patch delta 4888 zcmc)N&ubGw6bJCW>~6DkP1~eNwCzEIf<;K^QhHGoL!+l2dhiFxQo6Qd5>3pK4Z`LS zBSL9TsSahKg&f4{MN?%WbE;Ovlc}YpM?G0;BNRh11@+=u{2QKg+2e=r8|J;Yzh~V~ z7u{k}nrnM04hZD)$Z74eNwTJ9>gj}@N@-EUi0L_98_i7WDQzs9iD&h+sf}5=MCSIt z&yYH(rIOb*Gnpe{L!Z2*$BC(>iJ3?miDX!fsFC5YVGTvp!3c@RX-KtLUC6lbI9eBE z_N9GY#3R|ILn}bGkqVlpcRey&?tCF2lfj-NeWZz$@&Vfp`vn}1g;Y}^4WwiRT8PRl zde)SXNqyvlk9qNbd%a&BCbPFUTnbZ@yAx45)CFR|vr z1sR{E%>{{VJyt=+U`4mj z3(#-xRKP>uw8F27aMXo|a|bWAqZVD_nGOiZxTfuxUVf$rK6+4Lkyk_DmvBwnF@4-R z39caGxHI-ee(W67BwW*W%np7(2H*T>TWOwmUW1r`=h=?e&4qEOd2y<1>lV!L8wPA5 zZA{z&qXE2kVy{-fOP{xV_I%kX?VU0d5NFSU&YwJlX$7&@JCTnIc;4TT{ruS@kQKat e411P=pC_v@E#jfvL4#gWM_L&YeE2G#UOLM>-nu_*mjxJ^=?lx2 zgpJC!LpGQXNg3Vf)1KBLXcjXrth=NIPM?g;H}ttoz`kgG5Y=_{C-$?06_HZ)Q3n zAm%#2rjeYmoF0;$m!lV$H=BLn663wFq>-Gk+@VfcVqzx&R~3pdE#VU|0xN#m+KxUK zW^~#*Qso}($*+$8EdBsCblFQ6MH9{`($W3}@VCmhscDT@+-V)}UJgKLgtztrpQ;UjYiW74)5_5859199u5=#QRXW=X1UL1J=tVtQ(EOm1p%MrJ`qrmmr$p`NL3 zL8Y;tp@Cj%dio^6w8{Lui&G!b$FjD~@qATG^s#M|;Ci;ycl7aB-Q?eryqgmx@|fvs JW24M(Apj#E(xd$u!GbyGxvm{lwATc>RF+H_7CO5S>BeNhQQ`b<>P|sAi zpwd{+&_FLWJ$>>)-k8aMc;=;EriX2t5Axn%qK{QTkCksW7i42gy-yFH0j>$Rs Q`Jwm)COTUgD*aLj05g%*G5`Po delta 254 zcmewow=agZfpw~}-bU6E9`&YVtC-T_)S}{;;>6sH#GIU%;{4L0$u!GbyGxvm{lwATc>RF+H_7CO5S>BeNhQQ`b<>P|sAi zpwd{+&_FLWJ$-T?N6zGf?8{PL(ZjaQeH1W+!d11lL{NilF02_dHZ_E`fpsdE)<#xMcJ)cgRxzc;sYS&x#fiBYi8(nj#rdU0$*D0#sRjAPF}bP5 z8JPtcnUg09=S=?3zD#`$(dyeaPvGohB1OaG37j081$m{})OQeP%jSu~JD7=84D`bE J&8`w`!T`%hW{v;= diff --git a/docs/html/.doctrees/sections/Dataloaders/vector/implemented/ORAS5Current.doctree b/docs/html/.doctrees/sections/Dataloaders/vector/implemented/ORAS5Current.doctree index ba0b80b48db8d619aae86b9284b535ab45fa5a1a..1fd93da5d9cb88d29a2432925f136af41a4f0345 100644 GIT binary patch delta 568 zcmaDFGdrHOfpzKx{f(@O#Tg8MHrxq2*6es3pBo3{z*v8BGIlMj0~PZw8a NrjK=-A4;_d0{~6O)O7#= delta 153 zcmbOo|1^fRfpuz>-bU8l+^k*6RxzcMa~Y*La#M>lG7B;?Cr{u_ncT^$u!GbyGxvm{lwATc>RF+H_7CO5S>BeNhQQ`b<>P|sAi zpwd{+&_FLWJ$*8xbkJmO-kGUK>112tW*xpTCi+=7S%;5fvydP^Tk1tR`LJm7E^!5B M`dGJ_Q93~w0MUuf4gdfE delta 149 zcmbOp|1gHNfpuz_-bU759@dIvtC-Ts*^E*gxv9k&nFSe{lN}_2CVTSEWNpVLmAH8Y hUl$u!GbyGxvm{lwATc>RF+H_7CO5S>BeNhQQ`b<>P|sAi zpwd{+&_FLWJ$-TkTioPTtn*W^(ZjaQ1#AzP=wlVoV^y0!a$aOjeMAqR0j(>Ve1VT| QbEbd?6P>M$5Y`n20MDS)TmS$7 delta 250 zcmdn(-|EZSz&f=`Z6m7!t9nbaRZMAdYEf}aabj*pVopv>aeir0a%xObYC(Q+Om1p% zMrJ`q=43;zxXCYA=c~^kT7A{#H1;$mVl`|wOYT-ta?JJhn%fqLW@(2ierisb2Acia$+0{3S1IP5@USwlM{1d z0*dm}ixP8-V*)BmGV=4Fl(C^fOipG}OmSvOs%}AIa&}^RYH>_%YH>zpK}M#op`M|h zscu1~v7VuUUTS*!UqjenOlh{&U(!+O~56bp4)5j`c gv~_J}RGQ13`iLGr16o(S*+Op_6CJIqFuX4c07!-=w*UYD delta 356 zcmeC2#CW}rk+p$!s*n3dRy`s0mSn4#(&E&j;+W#Z+>FGWoS5SL(xT+ln4;8z{NkA0 z)Z&cHf{e^bB5{+y2`yEhL7ehUBCnZtQ=0ZRUj!~g&Q diff --git a/docs/html/.doctrees/sections/Installation.doctree b/docs/html/.doctrees/sections/Installation.doctree index af2b0a4d5557acf42924fc65553014a655601372..dfa7cc2bee1fb9ae5cd512f1ce1721684df39a12 100644 GIT binary patch delta 718 zcmZ4G^Us^LfpzL<)s3v&Y&OE4dBr7(IXRhm=?cE7#Tl6a8JSZu*kh+;i1lEVYn{?K zrFM!&hIB^qH=U;CuS%E!&)_VN)M8>0!(^x57%lr+0vv8Jxxfcvqq>fGB6+q_vUUMX-08Kcw>`{ zU}TjCM%LlU?^u;4bMeJVr~r-Q>|x2vFG-y;c?!(jp5>Dp_?kIj!8DndUxyJxNQqet zQ=RPOX#%#a>OecbPG;m#nEXSaf>CR8plO?DH`VKkY%S-6DJ zY%-su#AXK(0VYPP$$?^pj80&I+hU6t8Qp*a5|gJ%lr#En=96S&WDJ}vDisOTm@gH^ ZD7*QXR5T}}z~r5(N{j-VT~(ek0sur|^A7+3 delta 684 zcma)3-77<3828B8IomL{HnaJ78=EPnSdlBjg>NDGNEw~>uI8M>&MA^2iZn^jaid&t zM@c&Oa_PdYKSANbog0=MW=y8sKEKa?&ujNd53|DTmHW;avmt2j6k>8H8jT2HG9X4n z^Mj%y^D1R0RqBXmMzO^(Y?&RVe3}9e4dD#8DOA`Yyy1L!$2LGdmT*D^@A!buFiDFt6$KLGWkm`|izJdPnyU7Pi|>CfsBm3Sh?krluULXF zTxU~}6p>OPM0%g1c0PTJzi@mo_BPr-+vzjberS`@5UtR6^iHbrG(yt+gMdq}GTbz6 z6Sp!=1J$eQvg)VIs2{Sje$K1$xo*I|T-KTq8wDuEi@bHGNB1$ta|BWUA*w0E_%V*> zubIB5!2^rO{FRppu7qEj-hy$)OWpJdcPj{97c78Z>nIEZ)ZnSL4?LK#Zb3b6*klN5 z37bC~n$YW*gBDEKoZ6Y=2%sGYojcI|e!yqvBlP2a@tCe@bB%yo+jmVE!Ghaf4_LI~ H%3F8?KgjW? diff --git a/docs/html/_sources/index.rst.txt b/docs/html/_sources/index.rst.txt index 741a087b..c8b99f33 100644 --- a/docs/html/_sources/index.rst.txt +++ b/docs/html/_sources/index.rst.txt @@ -20,13 +20,12 @@ Contents: :maxdepth: 2 :numbered: - ./sections/Code_overview ./sections/Installation ./sections/ipython_notebooks ./sections/Command_line_interface + ./sections/Code_overview ./sections/Configuration/Configuration_overview ./sections/Outputs ./sections/Dataloaders/overview ./sections/Mesh_Construction/Mesh_construction_overview - ./sections/Examples ./sections/Plotting/mesh_plotting diff --git a/docs/html/_sources/sections/Installation.rst.txt b/docs/html/_sources/sections/Installation.rst.txt index b1f20ca1..94dd12b5 100644 --- a/docs/html/_sources/sections/Installation.rst.txt +++ b/docs/html/_sources/sections/Installation.rst.txt @@ -6,27 +6,29 @@ In this section we will outline the installation steps for installing the softwa The first stage is installing a version of Python 3.9, if you don't have a working version. We suggest installing a working Anaconda distribution from https://www.anaconda.com/products/distribution#macos following the instructions on that page. -Installing PolarRoute +Installing MeshiPhi ##################### -The PolarRoute software can be installed on Windows/Linux/MacOS by running one of the two following commands. +The MeshiPhi software can be installed on Windows/Linux/MacOS by running one of the two following commands. -Github: + +Pip: :: - git clone https://https://github.com/antarctica/PolarRoute.git - python setup.py install + pip install MeshiPhi -Pip: +Github: :: - pip install polar-route + git clone https://github.com/antarctica/MeshiPhi.git + cd MeshiPhi + pip install . Installing GDAL ############### -The PolarRoute software has GDAL as an optional requirement. It is only used when exporting TIFF images, +The MeshiPhi software has GDAL as an optional requirement. It is only used when exporting TIFF images, so if this is not useful to you, we would recommend steering clear. It is not trivial and is a common source of problems. With that said, below are instructions for various operating systems. @@ -35,7 +37,7 @@ Windows .. note:: We assume a version of Windows 10 or higher, with a working version of Python 3.9 including pip installed. - We recommend installing PolarRoute into a virtual environment. + We recommend installing MeshiPhi into a virtual environment. Windows: diff --git a/docs/html/genindex.html b/docs/html/genindex.html index c03e3964..57aef635 100644 --- a/docs/html/genindex.html +++ b/docs/html/genindex.html @@ -42,16 +42,15 @@

@@ -94,7 +93,6 @@

Index

| M | N | O - | P | R | S | T @@ -123,8 +121,6 @@

_

  • (meshiphi.mesh_generation.mesh_builder.MeshBuilder method)
  • (meshiphi.mesh_generation.metadata.Metadata method) -
  • -
  • (meshiphi.mesh_plotting.mesh_plotter.MeshPlotter method)
  • (meshiphi.mesh_validation.mesh_validator.MeshValidator method)
  • @@ -713,6 +709,8 @@

    M

  • module
  • + +
    • meshiphi.dataloaders.vector.vector_csv @@ -720,8 +718,6 @@

      M

    • module
    - -
    • meshiphi.dataloaders.vector.vector_grf @@ -769,13 +765,6 @@

      M

    • -
    • - meshiphi.mesh_plotting.mesh_plotter - -
    • @@ -792,8 +781,6 @@

      M

    • module
    -
  • MeshPlotter (class in meshiphi.mesh_plotting.mesh_plotter) -
  • MeshValidator (class in meshiphi.mesh_validation.mesh_validator)
  • Metadata (class in meshiphi.mesh_generation.metadata) @@ -887,8 +874,6 @@

    M

  • meshiphi.mesh_generation.metadata
  • meshiphi.mesh_generation.neighbour_graph -
  • -
  • meshiphi.mesh_plotting.mesh_plotter
  • meshiphi.mesh_validation.mesh_validator
  • @@ -926,18 +911,6 @@

    O

    -

    P

    - - - -
    -

    R

    - - - or other required elements. + thead: [ 1, "
      @@ -958,11 +931,7 @@

      S

    • Sampler (class in meshiphi.mesh_validation.sampler)
    • save() (meshiphi.mesh_generation.environment_mesh.EnvironmentMesh method) - -
    • ScalarCSVDataLoader (class in meshiphi.dataloaders.scalar.scalar_csv)
    • ScalarDataLoader (class in meshiphi.dataloaders.scalar.abstract_scalar) diff --git a/docs/html/index.html b/docs/html/index.html index 3ad54cf3..f08c0a4b 100644 --- a/docs/html/index.html +++ b/docs/html/index.html @@ -21,7 +21,7 @@ - + @@ -44,16 +44,15 @@ @@ -97,25 +96,24 @@

      Welcome to the MeshiPhi Manual Pages
        -
      • 1. Background
          -
        • 1.1. Code Overview
        • -
        • 1.2. Code Structure
        • +
        • 1. Installation
        • -
        • 2. Installation
            -
          • 2.1. Installing PolarRoute
          • -
          • 2.2. Installing GDAL
          • +
          • 2. Examples
          • -
          • 3. Python & iPython Notebooks
              -
            • 3.1. Creating the digital environment.
            • +
            • 3. Command Line Interface
            • -
            • 4. Command Line Interface @@ -161,7 +153,7 @@

              Welcome to the MeshiPhi Manual Pages - +
              diff --git a/docs/html/objects.inv b/docs/html/objects.inv index 863ddccd58a9f93a276aa14f3d769fbfda0c19a3..edacf06d0b10037819d57899b75c8f31c9677df8 100644 GIT binary patch delta 5265 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 @@ -307,11 +306,6 @@

              Python Module Index

        meshiphi.mesh_generation.neighbour_graph
        - meshiphi.mesh_plotting.mesh_plotter -
        diff --git a/docs/html/search.html b/docs/html/search.html index 1f6b3ff7..2fe07ae5 100644 --- a/docs/html/search.html +++ b/docs/html/search.html @@ -45,16 +45,15 @@ diff --git a/docs/html/searchindex.js b/docs/html/searchindex.js index e92c1072..ab8138e9 100644 --- a/docs/html/searchindex.js +++ b/docs/html/searchindex.js @@ -1 +1 @@ -Search.setIndex({"docnames": ["index", "sections/Code_overview", "sections/Command_line_interface", "sections/Configuration/Configuration_overview", "sections/Configuration/Mesh_construction_config", "sections/Dataloaders/AddingDataloaders", "sections/Dataloaders/DataLoaderInterface", "sections/Dataloaders/Factory", "sections/Dataloaders/lut/abstractLUT", "sections/Dataloaders/lut/implemented/Density", "sections/Dataloaders/lut/implemented/LutCSV", "sections/Dataloaders/lut/implemented/LutGeoJSON", "sections/Dataloaders/lut/implemented/Scotland_NCMPA", "sections/Dataloaders/lut/implemented/Thickness", "sections/Dataloaders/lut/index", "sections/Dataloaders/overview", "sections/Dataloaders/scalar/abstractScalar", "sections/Dataloaders/scalar/implemented/AMSR", "sections/Dataloaders/scalar/implemented/BSOSEDepth", "sections/Dataloaders/scalar/implemented/BSOSESeaIce", "sections/Dataloaders/scalar/implemented/BalticSeaIce", "sections/Dataloaders/scalar/implemented/BinaryGRF", "sections/Dataloaders/scalar/implemented/ERA5MaxWaveHeight", "sections/Dataloaders/scalar/implemented/ERA5SigWaveHeight", "sections/Dataloaders/scalar/implemented/ERA5WaveDirection", "sections/Dataloaders/scalar/implemented/ERA5WavePeriod", "sections/Dataloaders/scalar/implemented/ERA5WindDirection", "sections/Dataloaders/scalar/implemented/ERA5WindMagnitude", "sections/Dataloaders/scalar/implemented/GEBCO", "sections/Dataloaders/scalar/implemented/IceNet", "sections/Dataloaders/scalar/implemented/MODIS", "sections/Dataloaders/scalar/implemented/ScalarCSV", "sections/Dataloaders/scalar/implemented/ScalarGRF", "sections/Dataloaders/scalar/implemented/Shape", "sections/Dataloaders/scalar/index", "sections/Dataloaders/vector/abstractVector", "sections/Dataloaders/vector/implemented/BalticCurrent", "sections/Dataloaders/vector/implemented/DUACS", "sections/Dataloaders/vector/implemented/ERA5WaveDirection", "sections/Dataloaders/vector/implemented/ERA5Wind", "sections/Dataloaders/vector/implemented/NorthSeaCurrent", "sections/Dataloaders/vector/implemented/ORAS5Current", "sections/Dataloaders/vector/implemented/SOSE", "sections/Dataloaders/vector/implemented/VectorCSV", "sections/Dataloaders/vector/implemented/VectorGRF", "sections/Dataloaders/vector/index", "sections/Examples", "sections/Installation", "sections/Mesh_Construction/Mesh_construction_classes", "sections/Mesh_Construction/Mesh_construction_overview", "sections/Mesh_Construction/Mesh_validation", "sections/Outputs", "sections/Plotting/mesh_plotting", "sections/ipython_notebooks"], "filenames": ["index.rst", "sections\\Code_overview.rst", "sections\\Command_line_interface.rst", "sections\\Configuration\\Configuration_overview.rst", "sections\\Configuration\\Mesh_construction_config.rst", "sections\\Dataloaders\\AddingDataloaders.rst", "sections\\Dataloaders\\DataLoaderInterface.rst", "sections\\Dataloaders\\Factory.rst", "sections\\Dataloaders\\lut\\abstractLUT.rst", "sections\\Dataloaders\\lut\\implemented\\Density.rst", "sections\\Dataloaders\\lut\\implemented\\LutCSV.rst", "sections\\Dataloaders\\lut\\implemented\\LutGeoJSON.rst", "sections\\Dataloaders\\lut\\implemented\\Scotland_NCMPA.rst", "sections\\Dataloaders\\lut\\implemented\\Thickness.rst", "sections\\Dataloaders\\lut\\index.rst", "sections\\Dataloaders\\overview.rst", "sections\\Dataloaders\\scalar\\abstractScalar.rst", "sections\\Dataloaders\\scalar\\implemented\\AMSR.rst", "sections\\Dataloaders\\scalar\\implemented\\BSOSEDepth.rst", "sections\\Dataloaders\\scalar\\implemented\\BSOSESeaIce.rst", "sections\\Dataloaders\\scalar\\implemented\\BalticSeaIce.rst", "sections\\Dataloaders\\scalar\\implemented\\BinaryGRF.rst", "sections\\Dataloaders\\scalar\\implemented\\ERA5MaxWaveHeight.rst", "sections\\Dataloaders\\scalar\\implemented\\ERA5SigWaveHeight.rst", "sections\\Dataloaders\\scalar\\implemented\\ERA5WaveDirection.rst", "sections\\Dataloaders\\scalar\\implemented\\ERA5WavePeriod.rst", "sections\\Dataloaders\\scalar\\implemented\\ERA5WindDirection.rst", "sections\\Dataloaders\\scalar\\implemented\\ERA5WindMagnitude.rst", "sections\\Dataloaders\\scalar\\implemented\\GEBCO.rst", "sections\\Dataloaders\\scalar\\implemented\\IceNet.rst", "sections\\Dataloaders\\scalar\\implemented\\MODIS.rst", "sections\\Dataloaders\\scalar\\implemented\\ScalarCSV.rst", "sections\\Dataloaders\\scalar\\implemented\\ScalarGRF.rst", "sections\\Dataloaders\\scalar\\implemented\\Shape.rst", "sections\\Dataloaders\\scalar\\index.rst", "sections\\Dataloaders\\vector\\abstractVector.rst", "sections\\Dataloaders\\vector\\implemented\\BalticCurrent.rst", "sections\\Dataloaders\\vector\\implemented\\DUACS.rst", "sections\\Dataloaders\\vector\\implemented\\ERA5WaveDirection.rst", "sections\\Dataloaders\\vector\\implemented\\ERA5Wind.rst", "sections\\Dataloaders\\vector\\implemented\\NorthSeaCurrent.rst", "sections\\Dataloaders\\vector\\implemented\\ORAS5Current.rst", "sections\\Dataloaders\\vector\\implemented\\SOSE.rst", "sections\\Dataloaders\\vector\\implemented\\VectorCSV.rst", "sections\\Dataloaders\\vector\\implemented\\VectorGRF.rst", "sections\\Dataloaders\\vector\\index.rst", "sections\\Examples.rst", "sections\\Installation.rst", "sections\\Mesh_Construction\\Mesh_construction_classes.rst", "sections\\Mesh_Construction\\Mesh_construction_overview.rst", "sections\\Mesh_Construction\\Mesh_validation.rst", "sections\\Outputs.rst", "sections\\Plotting\\mesh_plotting.rst", "sections\\ipython_notebooks.rst"], "titles": ["Welcome to the MeshiPhi Manual Pages", "1. Background", "4. Command Line Interface", "5. Configuration Overview", "5.1. Configuration - Mesh Construction", "7.6. Adding New Dataloaders", "7.1. Dataloader Interface", "7.2. Dataloader Factory", "7.5.1.1. Abstract Look Up Table Dataloader", "7.5.3.1. Density Dataloader", "7.5.3.2. LUT CSV Dataloader", "7.5.3.3. LUT GeoJSON Dataloader", "7.5.3.4. Scotland NCMPA Dataloader", "7.5.3.5. Thickness Dataloader", "7.5. LUT Dataloaders", "7. Dataloader Overview", "7.3.1.1. Abstract Scalar Dataloader", "7.3.3.1. AMSR Dataloader", "7.3.3.2. BSOSE Depth Dataloader", "7.3.3.3. BSOSE Sea Ice Dataloader", "7.3.3.4. Baltic Sea Ice Dataloader", "7.3.3.5. Binary GRF Dataloader", "7.3.3.6. ERA5 Maximum Wave Height Dataloader", "7.3.3.7. ERA5 Significant Wave Height Dataloader", "7.3.3.8. ERA5 Mean Wave Direction Dataloader", "7.3.3.9. ERA5 Mean Wave Period Dataloader", "7.3.3.10. ERA5 Wind Direction Dataloader", "7.3.3.11. ERA5 Wind Magnitude Dataloader", "7.3.3.12. GEBCO Dataloader", "7.3.3.13. IceNet Dataloader", "7.3.3.14. MODIS Dataloader", "7.3.3.15. Scalar CSV Dataloader", "7.3.3.16. Scalar GRF Dataloader", "7.3.3.17. Shape Dataloader", "7.3. Scalar Dataloaders", "7.4.1.1. Abstract Vector Dataloader", "7.4.3.1. Baltic Currents Dataloader", "7.4.3.2. DUACS Currents Dataloader", "7.4.3.3. ERA5 Wave Direction Dataloader", "7.4.3.4. ERA5 Wind Dataloader", "7.4.3.5. North Sea Currents Dataloader", "7.4.3.6. ORAS5 Currents Dataloader", "7.4.3.7. SOSE Currents Dataloader", "7.4.3.8. Vector CSV Dataloader", "7.4.3.9. Vector GRF Dataloader", "7.4. Vector Dataloaders", "9. Examples of running code", "2. Installation", "8.4.1. Mesh Construction - Classes", "8. Methods - Mesh Construction", "8.4.2. Mesh Validation", "6. Outputs - Data Types", "10. Mesh Plotting", "3. Python & iPython Notebooks"], "terms": {"i": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 14, 15, 16, 17, 18, 19, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 37, 38, 39, 40, 41, 42, 43, 44, 45, 47, 48, 49, 50, 51, 53], "tool": [0, 1, 29], "discretis": [0, 1, 4], "environment": [0, 1, 5, 15, 48], "data": [0, 1, 2, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 48, 49, 50, 53], "non": [0, 4, 48], "uniform": [0, 4, 48, 50], "resolut": [0, 1, 2, 4, 22, 23, 24, 25, 26, 27, 30, 33, 38, 39, 48, 53], "base": [0, 1, 2, 4, 5, 7, 9, 12, 13, 15, 17, 20, 48, 50], "varianc": 0, "thi": [0, 1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 13, 15, 16, 17, 18, 19, 21, 31, 32, 33, 34, 35, 36, 38, 41, 42, 43, 45, 46, 47, 48, 49, 50, 51, 53], "softwar": [0, 1, 2, 3, 47], "packag": [0, 2, 3, 47, 48], "ha": [0, 2, 7, 9, 10, 11, 12, 13, 17, 18, 19, 20, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 36, 37, 38, 39, 40, 41, 42, 43, 44, 47, 48, 51], "been": [0, 2, 7, 15, 18, 19, 29, 42, 51], "develop": [0, 1, 29, 30, 37], "british": [0, 29], "antarct": [0, 9, 13, 29], "survei": [0, 29], "ba": 0, "initi": [0, 4, 7, 8, 9, 10, 11, 12, 13, 15, 16, 17, 18, 19, 20, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 48, 49, 50], "part": [0, 37, 51], "rout": [0, 1, 2, 3, 4, 47, 53], "plan": [0, 1, 2, 3, 51, 53], "research": [0, 17, 29], "vessel": [0, 1, 2, 3, 48, 51, 53], "rr": 0, "sir": 0, "david": 0, "attenborough": 0, "though": [0, 48], "can": [0, 1, 2, 3, 7, 8, 10, 12, 15, 16, 17, 18, 19, 20, 28, 30, 32, 33, 34, 35, 36, 37, 41, 42, 44, 45, 46, 47, 48, 49, 51, 53], "appli": [0, 1, 4, 51], "ani": [0, 2, 4, 8, 10, 11, 16, 31, 35, 43, 48, 51], "geospati": [0, 48], "The": [0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 31, 32, 33, 34, 35, 36, 37, 38, 39, 42, 43, 44, 45, 47, 48, 49, 52, 53], "written": [0, 3, 7], "python": [0, 1, 3, 46, 47], "open": [0, 1, 3, 5, 14, 34, 45, 48, 51, 53], "sourc": [0, 2, 7, 10, 11, 31, 33, 34, 43, 45, 47, 48, 50, 53], "contain": [0, 2, 4, 8, 11, 15, 16, 21, 32, 33, 35, 44, 48, 50, 51], "limit": [0, 7, 8, 9, 10, 11, 12, 13, 16, 17, 18, 19, 20, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 48], "plot": [0, 1, 4], "function": [0, 4, 5, 8, 14, 15, 16, 17, 34, 35, 45, 48, 53], "which": [0, 1, 2, 4, 6, 15, 16, 18, 21, 35, 38, 41, 48, 50, 51, 53], "describ": [0, 48, 49], "mesh": [0, 1, 2, 3, 5, 6, 7, 8, 10, 11, 14, 15, 16, 31, 33, 34, 35, 43, 45, 53], "section": [0, 1, 2, 3, 4, 46, 47, 48, 49, 51, 53], "For": [0, 7, 15, 32, 44, 48, 49, 51], "more": [0, 14, 15, 16, 18, 19, 34, 35, 40, 42, 45, 46, 48, 49, 51], "inform": [0, 1, 4, 22, 23, 24, 25, 26, 27, 30, 38, 39, 40, 48, 51], "project": [0, 2, 8, 15, 16, 18, 19, 34, 35, 42, 45, 48], "pleas": [0, 49], "visit": 0, "polarrout": [0, 3, 15, 46], "websit": [0, 18, 19, 22, 23, 24, 25, 26, 27, 29, 30, 37, 38, 39, 41, 42], "follow": [0, 1, 2, 4, 5, 7, 8, 15, 16, 32, 35, 44, 47, 48, 49, 51, 53], "our": [0, 1, 48], "github": [0, 2, 47], "repositori": [0, 47], "codebas": [0, 1], "ongo": 0, "yet": [0, 32, 44], "complet": [0, 8, 11, 16, 32, 33, 35, 44], "contact": 0, "content": 0, "background": 0, "code": [0, 2, 3, 6, 15, 48], "overview": [0, 48, 51], "structur": [0, 3, 9, 48, 51], "instal": 0, "gdal": 0, "ipython": [0, 46, 48], "notebook": [0, 46, 48], "creat": [0, 5, 7, 9, 12, 13, 14, 15, 32, 33, 34, 44, 45, 48], "digit": [0, 1, 2], "environ": [0, 2, 4, 47, 48, 49, 51], "command": [0, 3, 46, 47], "line": [0, 3, 4, 34, 45, 46, 48], "interfac": [0, 5, 15], "create_mesh": [0, 53], "export_mesh": 0, "rebuild_mesh": 0, "configur": [0, 1, 2, 48, 49, 51, 53], "construct": [0, 1, 2, 3, 10, 11, 15, 31, 33, 43, 50, 51, 53], "config": [0, 2, 4, 5, 7, 8, 10, 11, 15, 16, 19, 21, 32, 33, 35, 44, 47, 48, 50, 51, 53], "valid": [0, 49], "output": [0, 1, 2, 15, 16, 34, 35, 45], "type": [0, 1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 12, 13, 16, 17, 18, 19, 20, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 48, 50, 52], "json": [0, 2, 3, 5, 7, 48, 52, 53], "file": [0, 1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 45, 48, 50, 52, 53], "vessel_mesh": 0, "dataload": [0, 1, 48, 51], "factori": [0, 5, 15, 33, 45], "scalar": [0, 4, 5, 7, 8, 10, 11, 14, 15, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 33, 35, 44, 45], "vector": [0, 4, 7, 15, 32, 36, 37, 38, 39, 40, 41, 42, 48], "lut": [0, 7, 8, 9, 12, 13, 15], "ad": [0, 4, 15, 46, 48, 53], "new": [0, 14, 15, 18, 19, 34, 35, 42, 45, 48, 51], "method": [0, 1, 5, 6, 7, 8, 14, 15, 16, 33, 34, 35, 45, 48, 53], "design": [0, 10, 11, 31, 33, 43], "us": [0, 1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 13, 14, 15, 16, 18, 19, 21, 22, 23, 24, 25, 26, 27, 28, 31, 32, 33, 35, 38, 39, 42, 43, 44, 45, 47, 48, 50, 51, 52, 53], "case": [0, 4, 8, 15, 16, 35, 48, 51, 53], "addit": [0, 1, 11, 17, 37, 51, 53], "exampl": [0, 1, 3, 5, 15, 48, 51], "run": [0, 1, 2, 47, 48, 51], "1": [0, 4, 5, 13, 16, 20, 21, 30, 32, 33, 34, 35, 48, 51], "antarctica": [0, 47], "process": [0, 1, 2, 3, 4, 15, 37, 50, 51], "all": [0, 1, 3, 4, 6, 7, 8, 16, 22, 23, 24, 25, 26, 27, 34, 35, 38, 39, 45, 48, 50, 51], "stage": [0, 1, 2, 3, 47, 51], "planner": [0, 2, 4, 51], "2": [0, 4, 13, 16, 29, 30, 35, 48, 51], "dijkstra": 0, "v": [0, 2, 9, 38], "smooth": [0, 1], "path": [0, 2, 3, 48, 50], "variat": 0, "vehicl": [0, 1, 51], "properti": [0, 9, 51], "we": [1, 3, 15, 46, 47, 48, 49], "present": [1, 22, 23, 24, 25, 26, 27, 38, 39], "an": [1, 2, 4, 5, 7, 8, 13, 14, 15, 18, 19, 22, 23, 24, 25, 26, 27, 29, 33, 34, 35, 38, 45, 47, 48, 49, 50, 51], "autom": 1, "ic": [1, 9, 12, 13, 15, 17, 18, 29, 34, 36, 41, 48, 51], "strengthen": 1, "oper": [1, 4, 6, 8, 16, 20, 35, 37, 47, 51], "polar": [1, 47], "region": [1, 8, 10, 11, 13, 14, 48], "build": [1, 2, 4, 5, 48, 50], "underwat": 1, "long": [1, 8, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 48, 50, 51], "distanc": [1, 50, 51], "report": 1, "fox": 1, "et": [1, 9, 13, 29], "al": [1, 9, 13, 29], "2021": [1, 29], "start": [1, 4, 32, 33, 44, 48, 49, 51], "same": [1, 5, 8, 15, 16, 21, 35, 48, 53], "grid": [1, 4, 20, 22, 23, 24, 25, 26, 27, 37, 38, 39, 48], "approach": 1, "obtain": 1, "satisfi": [1, 4], "constraint": 1, "perform": [1, 2, 3, 4, 5, 7, 8, 10, 11, 16, 31, 35, 43, 48, 51], "ship": 1, "novel": 1, "result": [1, 48], "shorten": 1, "ensur": [1, 3, 15, 32], "great": 1, "circl": [1, 7, 33], "arc": 1, "where": [1, 2, 4, 8, 15, 16, 30, 35, 40, 48, 49, 51], "possibl": [1, 4, 8, 15, 16], "two": [1, 2, 7, 10, 15, 35, 44, 47, 48, 51], "effici": 1, "gener": [1, 4, 5, 6, 7, 8, 9, 13, 15, 16, 18, 19, 21, 22, 23, 24, 25, 26, 27, 28, 32, 33, 35, 38, 39, 40, 42, 44, 48, 49, 50, 51], "standard": [1, 3, 14, 34, 45, 48, 51], "navig": 1, "solut": [1, 18, 19], "water": 1, "optimis": [1, 53], "around": [1, 12, 21], "area": [1, 4, 12, 15, 36], "domin": 1, "sea": [1, 9, 12, 13, 15, 17, 18, 29, 34, 36, 37, 41, 45, 48], "while": [1, 15], "have": [1, 4, 7, 8, 10, 15, 16, 34, 35, 45, 47, 50, 51], "focuss": 1, "ar": [1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 14, 15, 16, 20, 21, 22, 23, 24, 25, 26, 27, 30, 32, 33, 34, 35, 36, 38, 39, 40, 44, 45, 47, 48, 51], "also": [1, 2, 3, 4, 17, 35, 53], "applic": [1, 16, 35], "broader": 1, "context": 1, "e": [1, 3, 4, 5, 15, 16, 35, 37, 45, 48], "g": [1, 3, 4, 5, 16, 35, 45, 48], "commerci": 1, "must": [1, 3, 4, 7, 8, 10, 14, 15, 16, 21, 32, 33, 34, 35, 44, 45], "respons": [1, 15], "chang": [1, 4, 8, 16, 35], "local": [1, 48], "weather": [1, 15, 22, 23, 24, 25, 26, 27, 38, 39, 41], "condit": [1, 4, 6, 7, 8, 15, 16, 35, 48, 51], "outlin": [1, 3, 46, 47, 48, 49], "manual": 1, "provid": [1, 2, 3, 7, 8, 11, 12, 14, 15, 16, 17, 18, 19, 20, 22, 23, 24, 25, 26, 27, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 44, 45, 48, 50], "user": [1, 2, 5, 8, 14, 15, 16, 34, 35, 45, 46, 51], "thei": [1, 3, 4, 15, 34, 45, 49], "need": [1, 5, 6, 7, 8, 14, 15, 16, 34, 35, 45, 53], "set": [1, 2, 4, 5, 7, 8, 11, 16, 21, 32, 33, 34, 35, 44, 45, 48, 51], "hope": 1, "suppli": [1, 3], "each": [1, 2, 3, 4, 5, 7, 8, 15, 16, 35, 48, 49, 50, 51], "allow": [1, 2, 3, 4, 7, 16, 35, 47], "understand": [1, 17], "throughout": [1, 46, 49], "toolkit": 1, "separ": [1, 3, 4, 5, 15, 45, 51], "broken": [1, 44], "down": [1, 15, 44, 51], "read": [1, 3, 5, 6, 7, 8, 10, 15, 17, 18, 19, 20, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 36, 37, 38, 39, 40, 41, 42, 43], "differ": [1, 14, 17, 21, 35, 37, 41, 45], "dataset": [1, 4, 8, 9, 10, 11, 12, 13, 15, 16, 17, 18, 19, 20, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45], "form": [1, 4, 6, 8, 16, 32, 33, 35, 44, 48, 51, 53], "input": [1, 3, 7, 48, 49], "should": [1, 4, 5, 8, 11, 15, 16, 35, 48, 50, 51], "take": [1, 4, 10, 11, 13, 31, 38, 43, 49, 50, 51], "tip": 1, "pre": [1, 48], "your": [1, 15], "twin": 1, "In": [1, 3, 4, 6, 7, 15, 32, 44, 46, 47, 48], "class": [1, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15, 16, 17, 18, 19, 20, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 49, 50, 51, 52], "represent": [1, 4, 48, 50, 51], "across": [1, 4], "defin": [1, 4, 5, 7, 8, 14, 15, 16, 17, 31, 32, 33, 34, 35, 43, 44, 45, 48, 51], "give": [1, 4, 37, 38], "dynam": [1, 37], "split": [1, 8, 15, 16, 48, 53], "finer": 1, "spatial": [1, 4, 15, 22, 23, 24, 25, 26, 27, 38, 39, 48, 50, 51], "vari": 1, "pipelin": [1, 51], "make": [1, 3, 4, 15, 51], "found": [1, 2, 3, 8, 16, 30, 46, 51], "document": [1, 2, 3, 21, 48, 51, 53], "produc": [1, 2, 7, 15, 17, 20, 22, 23, 24, 25, 26, 27, 32, 38, 39, 44, 48], "main": [1, 4, 15, 48, 49], "seri": [1, 16, 35, 46, 48], "interact": [1, 6, 49], "map": [1, 13, 29, 35, 48], "static": [1, 7], "figur": [1, 4, 49], "featur": [1, 48, 51], "These": [1, 3, 4, 15, 51], "later": 1, "caartographi": 2, "cli": [2, 53], "entri": [2, 5, 7, 8, 16, 35, 41, 51, 53], "point": [2, 4, 16, 35, 48, 51, 53], "intend": [2, 48], "success": 2, "through": [2, 3, 6, 8, 48, 53], "from": [2, 3, 5, 7, 8, 9, 10, 12, 13, 15, 16, 17, 18, 19, 20, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 45, 46, 47, 48, 49, 51, 52, 53], "collect": [2, 48], "model": [2, 3, 9, 18, 19, 40, 42, 48, 51], "posit": [2, 51], "argument": [2, 3], "A": [2, 4, 9, 13, 48, 49, 51, 53], "detail": [2, 4, 5, 14, 15, 34, 45, 48, 49], "how": [2, 4, 5, 6, 14, 15, 17, 22, 23, 24, 25, 26, 27, 34, 38, 39, 45, 48, 49], "parsabl": [2, 48], "format": [2, 5, 8, 14, 15, 16, 18, 19, 34, 35, 42, 45, 48, 49, 51, 53], "requir": [2, 4, 5, 7, 8, 11, 14, 15, 16, 32, 33, 34, 35, 44, 45, 47, 53], "option": [2, 3, 4, 5, 7, 8, 15, 47, 48], "verbos": 2, "log": [2, 34, 45], "o": [2, 47], "locat": [2, 7, 48, 51], "return": [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 48, 50, 51], "explain": 2, "onc": [2, 48, 51], "built": 2, "export": [2, 47, 48, 51], "other": [2, 4, 6, 16, 18, 19, 28, 36, 37, 42, 48, 49], "system": [2, 4, 16, 29, 35, 37, 40, 41, 47], "gi": 2, "output_loc": 2, "output_format": 2, "save": [2, 8, 11, 14, 16, 34, 35, 44, 45, 48, 51, 52, 53], "support": [2, 4, 8, 48], "default": [2, 4, 7, 8, 10, 11, 16, 21, 32, 33, 34, 35, 44, 45, 48, 51], "geo": [2, 48, 50], "polygon": [2, 8, 10, 11, 13, 14, 48], "cell": [2, 4, 48, 51], "geojson": [2, 12, 14, 15, 48, 51], "tif": [2, 48], "rasteris": 2, "format_conf": 2, "data_nam": [2, 4, 5, 6, 8, 10, 11, 16, 21, 32, 35, 44, 45, 48], "elev": [2, 4, 18, 28, 48, 51], "sampling_resolut": [2, 48], "150": [2, 48], "3031": [2, 48], "color_conf": 2, "txt": 2, "variabl": [2, 4, 8, 9, 12, 13, 15, 16, 17, 18, 19, 20, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44], "name": [2, 4, 5, 7, 8, 10, 13, 15, 16, 21, 32, 35, 44, 45, 48, 51, 52], "layer": [2, 36], "list": [2, 4, 7, 8, 10, 11, 16, 35, 48, 51, 53], "valu": [2, 3, 4, 6, 7, 8, 9, 10, 11, 13, 14, 15, 16, 17, 18, 19, 20, 21, 32, 33, 34, 35, 36, 41, 44, 45, 48, 50, 51, 52], "first": [2, 44, 47, 48, 51], "being": [2, 8, 11, 15, 16, 29, 32, 33, 34, 35, 44, 45, 48], "x": [2, 34, 35, 44, 45, 51], "second": [2, 44], "y": [2, 34, 35, 44, 45, 51], "string": [2, 3, 4, 10, 35, 45, 48, 50, 51], "epsg": [2, 8, 15, 16, 34, 35, 45, 48], "color": [2, 48], "text": [2, 48], "scheme": 2, "when": [2, 4, 6, 8, 11, 14, 15, 16, 34, 35, 45, 47, 48, 51], "0": [2, 4, 5, 21, 32, 33, 34, 44, 48, 51], "240": [2, 48], "250": [2, 48], "160": [2, 48], "30": [2, 48], "230": [2, 48], "220": [2, 48], "170": [2, 48], "60": [2, 4, 48], "100": [2, 48], "4": [2, 4, 13, 35, 48, 51], "column": [2, 8, 10, 11, 15, 16, 17, 21, 31, 32, 34, 35, 43, 44, 45, 48, 51], "per": [2, 13, 15, 21, 32, 44, 48], "correspond": [2, 35, 47, 48, 51], "red": [2, 48], "green": [2, 48], "blue": [2, 4, 48], "between": [2, 4, 16, 21, 33, 35, 48, 50, 51], "255": [2, 48], "onli": [2, 4, 5, 6, 7, 11, 15, 17, 21, 47], "specifi": [2, 4, 8, 10, 11, 13, 16, 19, 21, 32, 35, 50, 51], "you": [2, 5, 7, 47], "want": [2, 7, 8], "singl": [2, 4, 7, 8, 15, 16], "rebuild": 2, "origin": [2, 35, 48, 51], "store": [2, 4, 6, 7, 8, 15, 16, 35, 45, 48], "within": [2, 4, 6, 7, 8, 9, 13, 15, 16, 17, 18, 19, 20, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 48, 50, 51, 53], "primarili": [2, 10, 11, 31, 33, 43], "debug": [2, 5, 33, 34, 45], "updat": [2, 17, 35, 47, 48], "old": [2, 35], "older": 2, "version": [2, 47], "reappli": 2, "simul": [2, 9, 12, 13, 29, 33, 53], "were": [2, 9, 13, 35], "visualis": 2, "geoplot": 2, "librari": 2, "relev": [2, 35, 51], "page": [2, 4, 5, 14, 15, 21, 32, 34, 44, 45, 47], "qgi": 2, "common": [2, 4, 15, 28, 47], "portion": [3, 4], "pass": [3, 7, 17, 48, 51], "script": 3, "directori": 3, "descript": [3, 50, 51], "At": [3, 7], "major": 3, "templat": [3, 15], "schema": 3, "check": [3, 4, 16, 35, 48], "correct": [3, 7, 33], "keyword": [3, 4, 11], "datatyp": 3, "": [3, 4, 8, 15, 16, 17, 28, 30, 35, 48, 49, 50, 51], "well": [3, 33], "waypoint": 3, "csv": [3, 11, 14, 15, 34, 45, 51], "rudimentari": 3, "sens": [3, 15], "starttim": [3, 4, 51], "befor": [3, 4, 5, 32, 50], "endtim": [3, 4], "meshiphi": [3, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, 17, 18, 19, 20, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 48, 50, 51, 52, 53], "config_valid": 3, "flexi_json_input": 3, "flexibl": [3, 7, 15], "If": [3, 4, 5, 8, 16, 19, 35, 48], "pars": [3, 8, 16], "assum": [3, 5, 35, 47], "dict": [3, 4, 6, 7, 8, 11, 13, 16, 17, 32, 33, 35, 44, 48, 50], "alreadi": [3, 34, 45], "load": [3, 5, 10, 11, 15, 17, 31, 32, 33, 34, 43, 44, 45, 48, 51, 53], "paramet": [3, 4, 5, 7, 8, 9, 10, 11, 12, 13, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 48, 50, 53], "str": [3, 6, 7, 8, 16, 35, 48, 52], "translat": [3, 7, 17], "rais": [3, 8, 16, 19, 35], "typeerror": 3, "neither": 3, "nor": 3, "wrong": [3, 34, 45], "dictionari": [3, 4, 5, 6, 7, 8, 11, 16, 17, 32, 33, 35, 44, 48], "validate_mesh_config": 3, "tri": 3, "filenam": [3, 52], "incorrect": 3, "filenotfounderror": 3, "could": [3, 16, 35], "validationerror": 3, "malform": 3, "validate_route_config": 3, "validate_vessel_config": 3, "validate_waypoint": 3, "_summary_": 3, "pd": [3, 8, 9, 10, 11, 12, 13, 16, 29, 31, 32, 35, 43, 44, 51], "datafram": [3, 8, 9, 10, 11, 12, 13, 14, 15, 16, 21, 29, 31, 32, 34, 35, 43, 44, 45, 51], "_description_": 3, "assertionerror": [3, 8], "mesh_info": [4, 48], "latmin": 4, "65": 4, "latmax": 4, "longmin": 4, "70": 4, "longmax": 4, "50": [4, 51], "2013": 4, "03": 4, "01": [4, 51], "14": 4, "cellwidth": 4, "5": [4, 5, 7, 13, 21, 41, 48, 51], "cellheight": 4, "data_sourc": [4, 48], "loader": [4, 7, 21, 32, 44, 45, 48], "gebco": [4, 7, 34, 51], "param": [4, 5, 7, 8, 9, 10, 11, 12, 13, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 48, 50, 52], "downsample_factor": [4, 16, 35], "datastor": 4, "bathymetri": [4, 15], "gebco_2022_n": 4, "40": 4, "0_": 4, "90": 4, "0_w": 4, "140": 4, "0_e0": 4, "nc": 4, "value_fill_typ": [4, 48], "parent": [4, 48], "aggregate_typ": 4, "max": [4, 8, 16, 21, 32, 33, 35, 44, 48], "splitting_condit": [4, 5, 48], "threshold": [4, 5, 16, 21, 32, 35], "10": [4, 13, 32, 44, 47, 50, 52], "upper_bound": [4, 5, 16], "lower_bound": [4, 5, 16], "amsr": [4, 7, 34, 51], "folder": [4, 7, 17], "sic": [4, 17, 18, 19, 20, 29, 30, 48, 51], "amsr_south": 4, "hemispher": [4, 13, 17], "south": [4, 48, 51], "35": 4, "9": [4, 5, 13, 47], "sose": [4, 7, 18, 19, 45], "current": [4, 8, 15, 16, 17, 35, 45, 48], "sose_curr": 4, "sose_surface_velocity_6yearmean_2005": 4, "2010": 4, "uc": [4, 36, 37, 40, 41, 42, 44, 45], "vc": [4, 36, 37, 40, 41, 42, 44, 45], "curl": [4, 35], "04": 4, "thick": [4, 7, 9, 12, 14, 36, 51], "densiti": [4, 7, 13, 14, 15, 35, 51], "split_depth": [4, 48], "minimum_datapoint": [4, 48], "here": [4, 12, 17, 18, 19, 20, 22, 23, 24, 25, 26, 27, 28, 29, 30, 36, 37, 38, 39, 40, 41, 42], "dictat": [4, 15], "titl": [4, 10], "three": [4, 15], "primari": 4, "discret": [4, 48, 49, 51], "definit": [4, 51], "bound": [4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, 17, 18, 19, 20, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 48, 50], "tempor": [4, 15, 22, 23, 24, 25, 26, 27, 38, 39, 48], "interest": 4, "shape": [4, 8, 9, 10, 12, 14, 32, 34, 44], "box": [4, 48], "further": [4, 53], "given": [4, 13, 16, 48, 51], "below": [4, 5, 16, 21, 34, 35, 45, 47, 49, 51], "77": 4, "55": 4, "120": 4, "2017": [4, 51], "02": 4, "float": [4, 8, 13, 16, 35, 48, 50, 51], "degre": [4, 38, 51], "minimum": [4, 7, 16, 21, 32, 35, 44], "longitud": [4, 8, 15, 16, 35, 48, 51], "edg": [4, 8, 51], "maximum": [4, 21, 32, 34, 44, 48], "latitud": [4, 8, 15, 16, 35, 48, 51], "yyyi": [4, 48], "mm": [4, 48], "dd": [4, 48], "datetim": [4, 51], "time": [4, 7, 8, 15, 16, 31, 33, 34, 35, 37, 40, 43, 45, 48, 51], "averag": [4, 29, 35], "end": [4, 50, 51], "width": 4, "prior": 4, "height": [4, 24, 25, 26, 27, 34, 36, 38, 39], "refer": [4, 16, 35, 49], "todai": 4, "3": [4, 13, 21, 32, 44, 47, 48, 51], "item": 4, "repres": [4, 48, 50, 51], "add": [4, 5, 7, 15, 34, 35, 45, 47, 48, 50], "see": [4, 5, 21, 32, 44, 48, 49, 51], "abstractscalardataload": 4, "doc": [4, 14, 34, 45], "about": [4, 22, 23, 24, 25, 26, 27, 38, 39, 48, 49, 51], "avail": [4, 7, 8, 9, 13, 16, 17, 18, 19, 22, 23, 24, 25, 26, 27, 28, 29, 35, 36, 37, 38, 39, 40, 41, 42, 51], "mai": [4, 5, 6, 7, 15, 18, 19, 42, 45, 48, 51, 53], "includ": [4, 8, 15, 16, 22, 23, 24, 25, 26, 27, 32, 33, 34, 35, 36, 38, 39, 41, 44, 45, 47, 48, 51], "determin": [4, 6, 34, 35, 45, 48], "action": [4, 5, 7], "taken": [4, 9, 13, 15], "cellbox": [4, 16, 33, 35, 50], "either": [4, 8, 15, 16, 35, 45, 46, 53], "impli": 4, "assign": [4, 10, 11, 48, 51], "zero": 4, "nan": [4, 8, 10, 11, 16, 35], "aggreg": [4, 6, 8, 16, 35, 48, 50], "By": 4, "place": [4, 49, 50], "calcul": [4, 8, 16, 17, 35, 38, 48, 50], "mean": [4, 8, 16, 17, 18, 19, 34, 35, 36, 37, 38, 41, 42, 48], "min": [4, 8, 16, 21, 32, 33, 35, 44, 48], "count": [4, 8, 16, 35], "abov": [4, 16, 21, 35], "sub": 4, "divid": 4, "datapoint": [4, 7, 8, 15, 16, 21, 32, 33, 35, 44], "homogen": [4, 6, 7, 8, 16, 35, 48], "upperbound": [4, 16], "percentag": [4, 8, 16, 19, 35], "normalis": [4, 32], "deem": [4, 16], "greater": 4, "than": [4, 15, 16, 35], "lowerbound": [4, 16], "less": [4, 16, 35], "f": [4, 45, 48, 51, 53], "field": [4, 32, 35, 44], "order": [4, 15], "refin": 4, "done": [4, 53], "select": [4, 7, 8, 16, 33, 35], "divis": 4, "whenev": 4, "size": [4, 16, 21, 32, 33, 35, 44], "inhomogen": 4, "respect": [4, 37], "specif": [4, 7, 8, 15, 16, 35, 48, 51], "characterist": [4, 35], "ocean": [4, 15, 17, 18, 19, 22, 23, 24, 25, 26, 27, 28, 37, 38, 39, 40, 41, 42, 48], "depth": [4, 34, 36, 40, 41, 48, 49], "insid": [4, 48, 49], "illustr": [4, 49], "graphic": [4, 48, 51], "decis": 4, "shown": [4, 5], "histogram": 4, "arbitrari": 4, "orang": 4, "denot": 4, "formula": 4, "black": 4, "ub": 4, "upper": [4, 8, 16, 35], "lb": 4, "lower": [4, 8, 16, 35], "To": [4, 7, 15, 51], "probabl": 4, "distribut": [4, 9, 13, 21, 32, 44, 47, 48], "henc": 4, "under": [4, 5, 7, 50], "curv": 4, "decim": [4, 8, 16, 35, 50], "fraction": [4, 8, 16, 19, 35], "total": [4, 36, 51], "would": [4, 5, 14, 34, 45, 47, 50, 51], "show": [4, 6, 20], "decid": 4, "clr": [4, 8, 16, 35, 48], "hom": [4, 16, 48], "het": [4, 8, 16, 35, 48], "There": [4, 15], "fourth": 4, "trigger": [4, 35], "number": [4, 16, 21, 22, 23, 24, 25, 26, 27, 32, 35, 38, 39, 44, 48, 50], "do": [4, 5, 48], "extrem": 4, "alwai": [4, 15], "imagin": 4, "similar": [4, 45], "entir": [4, 30, 32], "both": [4, 7, 15], "colour": [4, 52], "meshbuild": [4, 5, 49], "subject": 4, "abl": 4, "implement": [5, 6, 15, 32, 44, 48], "object": [5, 8, 13, 15, 16, 17, 34, 35, 45, 48, 50, 51, 52, 53], "workflow": 5, "choos": 5, "appropri": [5, 7], "import_data": [5, 8, 9, 10, 11, 12, 13, 16, 17, 18, 19, 20, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45], "add_default_param": [5, 8, 11, 15, 16, 17, 32, 33, 34, 35, 44, 45], "abstractscalar": [5, 6, 15, 34, 45], "abstractvector": [5, 6, 14, 15, 45], "py": [5, 7, 47], "instruct": [5, 15, 22, 23, 24, 25, 26, 27, 38, 39, 47], "so": [5, 9, 13, 15, 34, 45, 47, 48], "after": [5, 48, 50, 51], "readi": 5, "go": 5, "It": [5, 10, 11, 17, 19, 21, 22, 23, 24, 25, 26, 27, 28, 31, 33, 38, 39, 42, 43, 47, 48, 49, 51], "purpos": 5, "__name__": 5, "__main__": 5, "test": [5, 10, 11, 15, 17, 31, 33, 43, 48], "its": [5, 48, 50, 51, 53], "deploi": 5, "wish": 5, "modifi": 5, "repo": 5, "one": [5, 7, 8, 15, 16, 35, 41, 47], "call": [5, 6, 7, 8, 16, 35, 49], "add_dataload": [5, 48], "re": 5, "work": [5, 14, 15, 18, 19, 34, 42, 45, 47], "out": [5, 8], "jupyt": [5, 48], "basic": 5, "step": [5, 16, 35, 47, 53], "import": [5, 7, 8, 10, 11, 14, 16, 34, 35, 45, 48, 51, 53], "abstract": [5, 6, 11, 17, 32, 33, 44, 48], "abstract_scalar": [5, 16], "scalardataload": [5, 16, 34, 45, 48], "up": [5, 14, 15, 22, 23, 24, 25, 26, 27, 38, 39], "wai": [5, 48, 50], "exist": [5, 15, 35, 48], "mydataload": [5, 34, 45, 48], "def": [5, 7, 34, 45], "self": [5, 7, 8, 15, 16, 34, 35, 45, 48, 50], "len": [5, 34], "xr": [5, 8, 16, 17, 18, 19, 20, 22, 23, 24, 25, 26, 27, 28, 30, 34, 35, 36, 37, 38, 39, 40, 41, 42, 45], "open_dataset": [5, 34, 45], "els": [5, 34, 48], "open_mfdataset": [5, 34, 45], "trim": [5, 8, 15, 16, 35], "boundari": [5, 6, 7, 8, 9, 10, 11, 12, 13, 15, 16, 17, 18, 19, 20, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 48, 51], "trim_datapoint": [5, 8, 16, 35], "initialis": [5, 7, 8, 16, 35, 48, 53], "path_to_file_1": [5, 7], "path_to_file_2": [5, 7], "popul": 5, "mani": [5, 16, 35, 41, 48], "my_data": 5, "r": [5, 48, 51, 53], "fp": 5, "mesh_build": [5, 48], "env_mesh": [5, 50], "build_environmental_mesh": [5, 48], "from_json": 5, "builder": 5, "regener": 5, "modified_build": 5, "modified_mesh": 5, "get_hom_condit": [6, 8, 16, 35], "get_valu": [6, 8, 13, 15, 16, 35], "realist": [6, 32, 44], "dataloader_interfac": 6, "dataloaderinterfac": 6, "intern": [6, 8, 15, 16, 18, 19, 29, 35, 42], "retriev": [6, 7, 8, 15, 16, 35], "splitting_cond": [6, 8, 16, 35], "heterogen": 6, "agg_typ": [6, 8, 16, 35], "np": 6, "float64": 6, "off": 7, "get_dataload": 7, "veri": 7, "least": [7, 8], "those": [7, 48], "third": 7, "dataloader_requir": 7, "myscalardataload": 7, "mandatori": 7, "get": [7, 47, 48, 50], "kei": [7, 8, 14, 16, 17, 35, 45], "statement": 7, "dataloaderfactori": 7, "min_dp": [7, 48], "myscalar": 7, "altern": [7, 15], "individu": [7, 35], "path_to_data_fil": 7, "path_to_fold": 7, "trail": 7, "quickli": 7, "scalar_csv": [7, 31], "scalar_grf": [7, 32], "binary_grf": [7, 21], "bsose_s": [7, 51], "bsose_depth": [7, 18, 51], "baltic_s": [7, 51], "icenet": [7, 34, 51], "modi": [7, 34, 51], "squar": [7, 33, 50], "gradient": [7, 33], "checkerboard": [7, 33], "vector_csv": [7, 43], "vector_grf": [7, 44], "baltic_curr": [7, 36], "era5_wind": [7, 39, 51], "northsea_curr": 7, "oras5_curr": [7, 41], "duacs_curr": [7, 37], "era5_wave_height": 7, "era5_wave_direct": 7, "space": [7, 50], "int": [7, 13, 21, 32, 44, 48, 50], "translate_file_input": 7, "abstract_lut": 8, "lutdataload": [8, 14], "lookup": 8, "__init__": [8, 13, 15, 16, 32, 35, 44, 48, 50, 52], "larg": [8, 15, 16, 22, 23, 24, 25, 26, 27, 35, 38, 39], "scale": [8, 16, 35], "downsampl": [8, 15, 16, 35], "reproject": [8, 15, 16, 17, 34, 35, 45], "renam": [8, 15, 16, 17, 18, 19, 20, 22, 23, 24, 25, 26, 27, 28, 29, 30, 34, 35, 36, 37, 38, 39, 40, 41, 42, 45], "scope": [8, 16, 35], "ingest": [8, 16, 18, 19, 35, 42], "uniqu": [8, 11, 16, 35], "upon": [8, 16, 35], "mercat": [8, 15, 16, 35], "4326": [8, 15, 16, 34, 35, 45, 48], "geometri": [8, 10, 11, 13, 48, 51], "gpd": 8, "valueerror": [8, 16, 19, 35], "li": [8, 16], "overload": [8, 16, 35], "extra": [8, 16, 35], "attribut": [8, 11, 16, 17, 32, 33, 35, 44, 45, 48, 50, 51], "calculate_coverag": [8, 16, 35], "none": [8, 16, 21, 32, 35, 44, 48], "cover": [8, 16, 22, 23, 24, 25, 26, 27, 35, 38, 39], "compar": [8, 16, 35, 50], "against": [8, 16, 35, 50, 53], "lookupt": 8, "get_data_col_nam": [8, 16, 35], "multipl": [8, 15, 16, 35], "t": [8, 16, 32, 34, 35, 45, 47], "datarang": [8, 16, 35], "analys": [8, 16, 35], "boolean": [8, 51, 52], "true": [8, 16, 21, 35, 48, 51], "goe": [8, 48], "homogenieti": [8, 16, 35], "condtion": [8, 16, 35], "get_val_from_coord": 8, "lat": [8, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 48, 50, 51], "return_coord": [8, 16, 35], "fals": [8, 16, 21, 32, 35], "extract": [8, 16, 35, 48], "kwarg": [8, 16, 35], "coordin": [8, 9, 12, 13, 15, 16, 17, 18, 19, 20, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 48, 51], "search": [8, 16, 35], "flag": [8, 21, 32, 35], "whether": [8, 16, 35, 51], "coord": 8, "optionali": 8, "associ": [8, 10, 14, 48], "skipna": [8, 16, 35], "aggregation_typ": [8, 16, 35], "accept": [8, 16, 35], "median": [8, 16, 35], "std": [8, 16, 35], "bool": [8, 16, 35, 48], "propog": [8, 16, 35], "aggregated_valu": [8, 16, 35], "even": [8, 16, 35], "scratch": [8, 16, 35], "set_data_col_nam": [8, 16, 35], "new_nam": [8, 16, 35], "replac": [8, 16, 35, 48], "verify_data": 8, "verifi": 8, "multipolygon": 8, "paper": [9, 13], "worbi": [9, 13], "p": [9, 13], "took": 9, "princip": 9, "strength": 9, "buynitskii": 9, "k": 9, "download": [9, 12, 13, 17, 18, 19, 20, 22, 23, 24, 25, 26, 27, 28, 30, 36, 37, 38, 39, 40, 41, 42], "densitydataload": 9, "scientif": [9, 12, 13], "literatur": [9, 12, 13], "date": [9, 12, 13], "density_df": 9, "cast": [10, 11, 15, 16, 31, 33, 35, 43, 53], "wa": [10, 11, 31, 33, 37, 40, 43, 51], "dummi": [10, 11, 31, 43], "As": [10, 18, 19, 31, 33, 42, 43, 51], "wkt": 10, "just": [10, 15], "lut_csv": 10, "lutcsv": 10, "outsid": [10, 11], "numpi": [10, 11, 50], "exclusion_df": [10, 11, 12], "lut_geojson": 11, "lutgeojson": 11, "over": [11, 16, 20], "regular": [11, 34, 45], "dummy_data": [11, 33], "scottish": 12, "govern": [12, 48], "natur": 12, "conserv": 12, "marin": [12, 15, 37], "protect": [12, 15], "scotland_ncmpa": 12, "scotlandncmpa": 12, "exclus": [12, 15], "zone": [12, 15], "thicknessdataload": 13, "value_dict": 13, "season": [13, 20, 29], "su": 13, "au": 13, "6": [13, 29], "wi": 13, "7": 13, "8": 13, "sp": 13, "11": 13, "12": [13, 51], "storag": [13, 48], "integ": [13, 50], "month": [13, 29], "account": 13, "jan": 13, "dec": 13, "thickness_df": 13, "look": [14, 15], "tabl": [14, 15], "hold": [14, 17, 34, 45], "most": [14, 34, 45], "manipul": [14, 16, 34, 35, 45, 53], "what": [14, 34, 45], "almost": [14, 45], "ident": [14, 45], "geopanda": [14, 15], "scotland": 14, "ncmpa": 14, "discuss": [15, 46, 48], "transform": [15, 16, 35, 48, 51], "raw": 15, "interpret": 15, "reduc": [15, 16, 22, 23, 24, 25, 26, 27, 35, 38, 39], "comput": [15, 37], "resourc": [15, 28], "typic": 15, "netcdf": [15, 17, 18, 19, 20, 22, 23, 24, 25, 26, 27, 28, 29, 30, 34, 36, 37, 38, 39, 40, 41, 42, 45], "howev": 15, "whatev": 15, "panda": [15, 17, 34, 45, 51], "xarrai": [15, 33, 34, 45], "uml": [15, 49], "diagram": [15, 49], "subsystem": 15, "concentr": [15, 17, 18, 19, 20, 29, 36, 48], "etc": [15, 51], "error": 15, "cut": 15, "correctli": 15, "multi": [15, 37, 49], "dimension": 15, "wind": [15, 34, 45, 51], "compon": [15, 35, 36, 38, 44, 45], "dimens": [15, 33, 35, 50], "n": [15, 16, 35, 50, 51], "rigor": 15, "real": [15, 32, 37, 44, 48], "prefer": 15, "localis": 15, "link": [15, 46], "categori": 15, "generalis": 15, "via": [15, 51], "extens": [15, 18, 19], "dask": 15, "own": 15, "utilis": 15, "much": 15, "memori": 15, "consumpt": [15, 51], "shapefil": 15, "otherwis": 15, "extent": [16, 35], "easili": [16, 18, 19, 34, 35, 42, 45], "factor": [16, 35], "m": [16, 35], "bin": [16, 35, 47], "get_dp_from_coord": [16, 35], "Will": [16, 35], "chosen": [16, 35], "becaus": [16, 35], "bad": [16, 35], "data_point": [16, 50], "split_lock": 16, "proport": 16, "higher": [16, 47, 50], "ignor": [16, 35], "happen": [16, 35], "in_proj": [16, 17, 34, 35, 45], "out_proj": [16, 17, 34, 35, 45], "x_col": [16, 17, 34, 35, 45], "y_col": [16, 17, 34, 35, 45], "pyproj": [16, 17, 35], "cr": [16, 35], "final": [16, 35, 44, 48], "shouldn": [16, 35], "advanc": 17, "microwav": 17, "scan": 17, "radiomet": 17, "publicli": [17, 18, 19, 28, 29, 41, 42], "earth": [17, 22, 23, 24, 25, 26, 27, 28, 30, 38, 39], "univers": 17, "bremen": 17, "standalon": 17, "independ": 17, "due": [17, 51], "issu": 17, "depend": 17, "caus": 17, "regress": [17, 48], "rectifi": 17, "soon": 17, "amsrdataload": 17, "turn": 17, "pair": 17, "drop": 17, "unnecessari": 17, "polar_stereograph": 17, "z": 17, "b": [18, 19], "biogeochem": [18, 19], "southern": [18, 19, 42], "state": [18, 19, 42], "estim": [18, 19, 22, 23, 24, 25, 26, 27, 37, 38, 39, 41, 42], "host": [18, 19], "amongst": [18, 19, 28, 37, 42], "product": [18, 19, 22, 23, 24, 25, 26, 27, 30, 36, 37, 38, 39, 42, 47], "Their": [18, 40], "led": [18, 19, 29, 42], "mazloff": [18, 19, 42], "scripp": [18, 19, 42], "institut": [18, 19, 20, 29, 36, 42], "oceanographi": [18, 19, 40, 42], "best": [18, 19, 42], "fit": [18, 19, 37, 42], "observ": [18, 19, 29, 42], "quantit": [18, 19, 42], "climatologi": [18, 19, 42], "note": [18, 19, 32, 42, 44, 48], "collat": [18, 19, 42], "bsosedepthdataload": 18, "bsose_sea_ic": 19, "bsoseseaicedataload": 19, "unit": [19, 38], "finnish": [20, 36], "meteorolog": [20, 36], "fmi": [20, 36], "webpag": [20, 36], "servic": [20, 37], "chart": [20, 28], "daili": [20, 36], "basi": 20, "dure": [20, 51], "km": 20, "baltic_sea_ic": 20, "balticseaicedataload": 20, "instead": 21, "consist": [21, 51], "land": [21, 22, 23, 24, 25, 26, 27, 38, 39, 51], "mask": [21, 32, 44], "seed": [21, 32, 44], "random": [21, 32, 44], "512": [21, 32, 44], "axi": [21, 32, 44], "alpha": [21, 32, 44], "power": [21, 32, 44], "law": [21, 32, 44], "momentum": [21, 32, 44], "famili": [22, 23, 24, 25, 26, 27, 38, 39], "european": [22, 23, 24, 25, 26, 27, 37, 38, 39, 41], "centr": [22, 23, 24, 25, 26, 27, 33, 38, 39, 40, 41], "medium": [22, 23, 24, 25, 26, 27, 38, 39, 41], "rang": [22, 23, 24, 25, 26, 27, 38, 39, 41, 48, 50, 51], "forecast": [22, 23, 24, 25, 26, 27, 29, 38, 39, 41], "ecmwf": [22, 23, 24, 25, 26, 27, 38, 39, 41], "fifth": [22, 23, 24, 25, 26, 27, 38, 39], "atmospher": [22, 23, 24, 25, 26, 27, 38, 39], "reanalysi": [22, 23, 24, 25, 26, 27, 36, 37, 38, 39, 41], "global": [22, 23, 24, 25, 26, 27, 37, 38, 39, 41, 48], "climat": [22, 23, 24, 25, 26, 27, 29, 38, 39], "period": [22, 23, 24, 26, 27, 34, 38, 39], "januari": [22, 23, 24, 25, 26, 27, 38, 39], "1950": [22, 23, 24, 25, 26, 27, 38, 39], "hourli": [22, 23, 24, 25, 26, 27, 38, 39], "30km": [22, 23, 24, 25, 26, 27, 38, 39], "resolv": [22, 23, 24, 25, 26, 27, 38, 39], "137": [22, 23, 24, 25, 26, 27, 38, 39], "level": [22, 23, 24, 25, 26, 27, 37, 38, 39], "surfac": [22, 23, 24, 25, 26, 27, 30, 36, 38, 39], "80km": [22, 23, 24, 25, 26, 27, 38, 39], "uncertainti": [22, 23, 24, 25, 26, 27, 38, 39], "era5_max_wave_height": 22, "era5maxwaveheightdataload": 22, "hmax": 22, "era5_sig_wave_height": 23, "era5sigwaveheightdataload": 23, "swh": 23, "era5_mean_wave_direct": 24, "era5meanwavedirdataload": 24, "mwd": [24, 38], "era5_wave_period": 25, "era5waveperioddataload": 25, "mwp": 25, "era5_wind_dir": 26, "era5winddirdataload": 26, "wave": [26, 27, 34, 45], "wind_dir": 26, "era5_wind_mag": 27, "era5windmagdataload": 27, "wind_mag": 27, "bathymetr": [28, 48], "scientist": 28, "gebcodataload": 28, "probabilist": 29, "deep": 29, "learn": 29, "team": 29, "alan": 29, "ture": 29, "andersson": 29, "train": 29, "next": 29, "monthli": [29, 36, 41], "v1": 29, "v2": 29, "icenetdataload": 29, "moder": 30, "imag": [30, 47, 48], "spectroradiomet": 30, "satellit": [30, 37], "born": 30, "instrument": 30, "nasa": 30, "view": 30, "everi": [30, 36], "dai": 30, "acquir": 30, "36": 30, "spectral": 30, "band": 30, "group": 30, "wavelength": 30, "modisdataload": 30, "scalarcsvdataload": 31, "potenti": [31, 43], "head": [31, 43, 47], "gaussian": [32, 44], "artifici": [32, 44], "somewhat": [32, 44], "world": [32, 44, 48], "binari": [32, 34, 44, 47], "isn": 32, "cap": 32, "skew": 32, "outlier": 32, "randomis": 32, "multipli": 32, "offset": 32, "actual": [32, 50], "actual_min": 32, "actual_max": 32, "scalargrfdataload": 32, "known": 33, "shapedataload": 33, "gen_checkerboard": 33, "pattern": 33, "gen_circl": 33, "radiu": 33, "gen_gradi": 33, "direct": [33, 34, 35, 45, 48], "act": [33, 51], "like": [33, 48], "simpli": 33, "enact": 33, "data_xr": 33, "simpl": [34, 45], "my": [34, 45], "aren": [34, 45], "lon": [34, 45], "trim_data": [34, 45], "sometim": [34, 45], "constant": [34, 45], "super": [34, 45], "3412": [34, 45], "strictli": [34, 45], "speak": [34, 45], "necessari": [34, 45], "becom": [34, 45], "skip": [34, 45], "now": [34, 45], "bsose": [34, 40], "baltic": [34, 45], "grf": [34, 45], "era5": [34, 45], "signific": 34, "magnitud": [34, 35, 44], "abstract_vector": 35, "vectordataload": [35, 45, 48], "add_mag_dir": 35, "easier": 35, "cartesian": 35, "data_name_list": 35, "_magnitud": 35, "_direct": 35, "calc_curl": 35, "collaps": 35, "collap": 35, "calc_diverg": 35, "diverg": 35, "div": 35, "calc_dmag": 35, "dmag": 35, "mag": 35, "mean_vector": 35, "calc_reynolds_numb": 35, "approxim": 35, "reynold": 35, "veloc": 35, "AND": 35, "viscos": 35, "OF": 35, "seawat": 35, "AT": 35, "c": 35, "WILL": 35, "minor": 35, "rework": 35, "TO": 35, "fluid": 35, "length": [35, 50], "append": 35, "comma": [35, 45], "seper": 35, "get_data_col_name_list": 35, "namesk": 35, "exceed": 35, "name_dict": 35, "old_nam": 35, "set_data_col_name_list": 35, "cmem": 36, "physic": 36, "whole": 36, "inclus": 36, "transit": 36, "north": [36, 38, 45, 48, 51], "hour": 36, "salin": 36, "temperatur": 36, "horizont": 36, "mix": 36, "bottom": 36, "balticcurrentdataload": 36, "copernicu": [36, 37], "mission": 37, "altimet": 37, "cne": 37, "cl": 37, "anomali": 37, "sla": 37, "twenti": 37, "year": 37, "1993": 37, "2012": 37, "optim": 37, "interpol": 37, "merg": 37, "l3": 37, "along": [37, 48, 51], "track": 37, "measur": 37, "absolut": 37, "topographi": 37, "geostroph": 37, "Near": 37, "duacscurrentdataload": 37, "deriv": 37, "come": [38, 48], "angl": [38, 51], "convert": [38, 48, 51], "u": 38, "era5_wave_direction_vector": 38, "era5wavedirectionload": 38, "uw": 38, "vw": 38, "era5winddataload": 39, "u10": [39, 51], "v10": [39, 51], "atlant": 40, "proudman": 40, "oceanograph": 40, "laboratori": 40, "coastal": 40, "polcom": 40, "uk": 40, "nation": 40, "liverpool": 40, "north_sea_curr": 40, "northseacurrentdataload": 40, "prepar": 41, "ocean5": 41, "analysi": 41, "compris": 41, "ensembl": 41, "member": 41, "publish": 41, "catalogu": 41, "oras5currentdataload": 41, "sosedataload": 42, "vectorcsvdataload": 43, "vec_x": 44, "vec_i": 44, "vectorgrfdataload": 44, "itself": 45, "duac": 45, "oras5": 45, "googl": 46, "colab": 46, "full": [46, 51], "procedur": 46, "shortli": 46, "don": 47, "suggest": 47, "anaconda": 47, "http": [47, 51], "www": 47, "com": 47, "git": 47, "clone": 47, "setup": 47, "pip": 47, "tiff": 47, "recommend": 47, "steer": 47, "clear": 47, "trivial": 47, "problem": 47, "With": 47, "said": 47, "variou": 47, "virtual": 47, "pipwin": 47, "easi": 47, "fiona": 47, "ubuntu": 47, "debian": 47, "sudo": 47, "apt": 47, "ppa": 47, "ubuntugi": 47, "libgdal": 47, "dev": 47, "cplus_include_path": 47, "usr": 47, "c_include_path": 47, "fedora": 47, "dnf": 47, "devel": 47, "homebrew": 47, "brew": 47, "modul": [48, 49], "behind": 48, "environmentalmesh": 48, "usag": 48, "execut": 48, "mesh_gener": 48, "respos": 48, "lat_min": 48, "lat_max": 48, "long_min": 48, "long_max": 48, "start_tim": 48, "end_tim": 48, "cell_width": 48, "cell_height": 48, "longtitud": 48, "180": 48, "j_grid": 48, "java": 48, "cellgrid": 48, "evironment": 48, "nonunifrom": 48, "neighbour": [48, 51], "graph": 48, "split_and_replac": 48, "smaller": 48, "four": 48, "corner": 48, "surround": 48, "split_to_depth": 48, "until": 48, "reach": 48, "mutabl": 48, "environment_mesh": 48, "agg_cellbox": 48, "neighbour_graph": 48, "conatin": [48, 50], "classmethod": 48, "load_from_json": 48, "mesh_json": [48, 51, 52], "env": [48, 50], "ex": 48, "format_param": 48, "to_geojson": 48, "params_fil": 48, "doe": 48, "to_json": [48, 51, 53], "them": 48, "connect": 48, "togeth": 48, "cellgird": 48, "parseabl": 48, "adjac": [48, 51], "to_tif": 48, "geotif": 48, "folow": 48, "fuel": [48, 51], "pixel": 48, "2d": 48, "arrai": [48, 50], "sampl": [48, 50], "geotiff": 48, "espg": 48, "colour_conf": 48, "update_cellbox": 48, "index": [48, 51], "certain": [48, 49], "perf": 48, "metric": 48, "encod": [48, 51], "grid_width": 48, "relationship": 48, "id": [48, 51], "id_1": [48, 51], "id_n": [48, 51], "get_neighbour_cas": 48, "cellbox_a": 48, "cellbox_b": 48, "touch": 48, "destin": 48, "east": [48, 51], "west": [48, 51], "initialise_neighbour_graph": 48, "update_neighbour": 48, "cellbox_indx": 48, "new_neighbours_indx": 48, "remov": [48, 51], "neighbour_map": 48, "new_neighbour_indx": 48, "cellbox_index": 48, "hous": 48, "access": [48, 50, 51], "numer": 48, "represnt": 48, "enabl": 48, "newli": 48, "logtitut": 48, "encapsul": 48, "set_data_sourc": 48, "spit": 48, "set_par": 48, "bigger": 48, "conain": 48, "got": 48, "should_split": 48, "stop_index": 48, "get_hom_cond": 48, "mixtur": 48, "stop": 48, "deprec": 48, "switch": 48, "breadth": 48, "start_id": 48, "represenst": 48, "usuallli": 48, "uniformli": 48, "among": 48, "data_load": [48, 51], "spliiting_condit": 48, "datasourc": 48, "assoc": 48, "indic": 48, "fill": [48, 50], "void": 48, "value_fill_tyep": 48, "aggregated_cellbox": 48, "agg_data": 48, "aggrgat": 48, "agg": 48, "contains_point": 48, "cx": [48, 51], "cy": [48, 51], "dcx": [48, 51], "dcy": [48, 51], "agg_value_1": 48, "agg_value_n": 48, "cell_json": 48, "compos": 49, "seen": 49, "depict": 49, "sequenc": [49, 50], "client": 49, "build_environment_mesh": 49, "event": 49, "explan": 49, "todo": 50, "mesh_valid": 50, "meshvalid": 50, "mesh_config_fil": 50, "conf": 50, "vlaidat": 50, "validation_length": 50, "legnth": 50, "wil": 50, "incur": 50, "cost": 50, "cellboox": 50, "environmentmesh": 50, "get_range_end": 50, "clacul": 50, "get_value_from_data": 50, "get_values_from_mesh": 50, "find": 50, "arg": 50, "validate_mesh": 50, "number_of_sampl": 50, "agg_valu": 50, "rmse": 50, "actaul": 50, "d": 50, "sobol": 50, "highli": 50, "guarante": 50, "better": 50, "coverag": 50, "generate_sampl": 50, "equal": 50, "fall": 50, "stream": 51, "understood": 51, "value_1": 51, "value_n": 51, "centroid": 51, "dxy": 51, "longer": 51, "inaccess": 51, "remain": 51, "contract": 51, "vessel_perform": 51, "vessel_performance_model": 51, "vesselperformancemodel": 51, "vessel_config": 51, "vpm": 51, "model_access": 51, "model_perform": 51, "vessel_mesh_json": 51, "still": 51, "without": 51, "miss": 51, "sda": 51, "speed": 51, "travel": 51, "rate": 51, "consid": 51, "reason": 51, "shallow": 51, "enough": 51, "ext_ic": 51, "resist": 51, "forc": 51, "encount": 51, "rel": 51, "appar": 51, "piplin": 51, "waypoints_path": 51, "ot": 51, "falkland": 51, "rothera": 51, "52": 51, "6347222222": 51, "75": 51, "26722": 51, "row": 51, "wgs84": 51, "waypoints_datafram": 51, "featurecollect": 51, "linestr": 51, "27": 51, "21694": 51, "07960297382266": 51, "619238882768894": 51, "hallei": 51, "traveltim": 51, "03531938671648596": 51, "050310986633880575": 51, "9648858923588642": 51, "3745886107069096": 51, "00": 51, "51": 51, "595036800": 51, "26": 51, "869276800": 51, "infor": 51, "org": 51, "meta": 51, "cumul": 51, "path_vari": 51, "utc": 51, "mesh_plot": 52, "mesh_plott": 52, "meshplott": 52, "figscal": 52, "matplotlib": 52, "cartopi": 52, "plot_bool": 52, "value_nam": 52, "plot_cmap": 52, "colourmap": 52, "termin": 53, "increas": 53, "alter": 53, "cg": 53, "dump": 53}, "objects": {"meshiphi.config_validation": [[3, 0, 0, "-", "config_validator"]], "meshiphi.config_validation.config_validator": [[3, 1, 1, "", "flexi_json_input"], [3, 1, 1, "", "validate_mesh_config"], [3, 1, 1, "", "validate_route_config"], [3, 1, 1, "", "validate_vessel_config"], [3, 1, 1, "", "validate_waypoints"]], "meshiphi.dataloaders": [[6, 0, 0, "-", "dataloader_interface"], [7, 0, 0, "-", "factory"]], "meshiphi.dataloaders.dataloader_interface": [[6, 2, 1, "", "DataLoaderInterface"]], "meshiphi.dataloaders.dataloader_interface.DataLoaderInterface": [[6, 3, 1, "", "get_hom_condition"], [6, 3, 1, "", "get_value"]], "meshiphi.dataloaders.factory": [[7, 2, 1, "", "DataLoaderFactory"]], "meshiphi.dataloaders.factory.DataLoaderFactory": [[7, 3, 1, "", "get_dataloader"], [7, 3, 1, "", "translate_file_input"]], "meshiphi.dataloaders.lut": [[8, 0, 0, "-", "abstract_lut"], [9, 0, 0, "-", "density"], [10, 0, 0, "-", "lut_csv"], [11, 0, 0, "-", "lut_geojson"], [12, 0, 0, "-", "scotland_ncmpa"], [13, 0, 0, "-", "thickness"]], "meshiphi.dataloaders.lut.abstract_lut": [[8, 2, 1, "", "LutDataLoader"]], "meshiphi.dataloaders.lut.abstract_lut.LutDataLoader": [[8, 3, 1, "", "__init__"], [8, 3, 1, "", "add_default_params"], [8, 3, 1, "", "calculate_coverage"], [8, 3, 1, "", "downsample"], [8, 3, 1, "", "get_data_col_name"], [8, 3, 1, "", "get_hom_condition"], [8, 3, 1, "", "get_val_from_coord"], [8, 3, 1, "", "get_value"], [8, 3, 1, "", "import_data"], [8, 3, 1, "", "reproject"], [8, 3, 1, "", "set_data_col_name"], [8, 3, 1, "", "trim_datapoints"], [8, 3, 1, "", "verify_data"]], "meshiphi.dataloaders.lut.abstract_lut.LutDataLoader.self": [[8, 4, 1, "", "data"], [8, 4, 1, "", "data_name"]], "meshiphi.dataloaders.lut.density": [[9, 2, 1, "", "DensityDataLoader"]], "meshiphi.dataloaders.lut.density.DensityDataLoader": [[9, 3, 1, "", "import_data"]], "meshiphi.dataloaders.lut.lut_csv": [[10, 2, 1, "", "LutCSV"]], "meshiphi.dataloaders.lut.lut_csv.LutCSV": [[10, 3, 1, "", "import_data"]], "meshiphi.dataloaders.lut.lut_geojson": [[11, 2, 1, "", "LutGeoJSON"]], "meshiphi.dataloaders.lut.lut_geojson.LutGeoJSON": [[11, 3, 1, "", "add_default_params"], [11, 3, 1, "", "import_data"]], "meshiphi.dataloaders.lut.scotland_ncmpa": [[12, 2, 1, "", "ScotlandNCMPA"]], "meshiphi.dataloaders.lut.scotland_ncmpa.ScotlandNCMPA": [[12, 3, 1, "", "import_data"]], "meshiphi.dataloaders.lut.thickness": [[13, 2, 1, "", "ThicknessDataLoader"]], "meshiphi.dataloaders.lut.thickness.ThicknessDataLoader": [[13, 2, 1, "", "Region"], [13, 3, 1, "", "import_data"]], "meshiphi.dataloaders.lut.thickness.ThicknessDataLoader.Region": [[13, 3, 1, "", "__init__"], [13, 3, 1, "", "get_value"]], "meshiphi.dataloaders.scalar": [[16, 0, 0, "-", "abstract_scalar"], [17, 0, 0, "-", "amsr"], [20, 0, 0, "-", "baltic_sea_ice"], [18, 0, 0, "-", "bsose_depth"], [19, 0, 0, "-", "bsose_sea_ice"], [22, 0, 0, "-", "era5_max_wave_height"], [24, 0, 0, "-", "era5_mean_wave_direction"], [23, 0, 0, "-", "era5_sig_wave_height"], [25, 0, 0, "-", "era5_wave_period"], [26, 0, 0, "-", "era5_wind_dir"], [27, 0, 0, "-", "era5_wind_mag"], [28, 0, 0, "-", "gebco"], [29, 0, 0, "-", "icenet"], [30, 0, 0, "-", "modis"], [31, 0, 0, "-", "scalar_csv"], [32, 0, 0, "-", "scalar_grf"], [33, 0, 0, "-", "shape"]], "meshiphi.dataloaders.scalar.abstract_scalar": [[16, 2, 1, "", "ScalarDataLoader"]], "meshiphi.dataloaders.scalar.abstract_scalar.ScalarDataLoader": [[16, 3, 1, "", "__init__"], [16, 3, 1, "", "add_default_params"], [16, 3, 1, "", "calculate_coverage"], [16, 3, 1, "", "downsample"], [16, 3, 1, "", "get_data_col_name"], [16, 3, 1, "", "get_dp_from_coord"], [16, 3, 1, "", "get_hom_condition"], [16, 3, 1, "", "get_value"], [16, 3, 1, "", "import_data"], [16, 3, 1, "", "reproject"], [16, 3, 1, "", "set_data_col_name"], [16, 3, 1, "", "trim_datapoints"]], "meshiphi.dataloaders.scalar.abstract_scalar.ScalarDataLoader.self": [[16, 4, 1, "", "data"], [16, 4, 1, "", "data_name"]], "meshiphi.dataloaders.scalar.amsr": [[17, 2, 1, "", "AMSRDataLoader"]], "meshiphi.dataloaders.scalar.amsr.AMSRDataLoader": [[17, 3, 1, "", "add_default_params"], [17, 3, 1, "", "import_data"]], "meshiphi.dataloaders.scalar.baltic_sea_ice": [[20, 2, 1, "", "BalticSeaIceDataLoader"]], "meshiphi.dataloaders.scalar.baltic_sea_ice.BalticSeaIceDataLoader": [[20, 3, 1, "", "import_data"]], "meshiphi.dataloaders.scalar.bsose_depth": [[18, 2, 1, "", "BSOSEDepthDataLoader"]], "meshiphi.dataloaders.scalar.bsose_depth.BSOSEDepthDataLoader": [[18, 3, 1, "", "import_data"]], "meshiphi.dataloaders.scalar.bsose_sea_ice": [[19, 2, 1, "", "BSOSESeaIceDataLoader"]], "meshiphi.dataloaders.scalar.bsose_sea_ice.BSOSESeaIceDataLoader": [[19, 3, 1, "", "import_data"]], "meshiphi.dataloaders.scalar.era5_max_wave_height": [[22, 2, 1, "", "ERA5MaxWaveHeightDataLoader"]], "meshiphi.dataloaders.scalar.era5_max_wave_height.ERA5MaxWaveHeightDataLoader": [[22, 3, 1, "", "import_data"]], "meshiphi.dataloaders.scalar.era5_mean_wave_direction": [[24, 2, 1, "", "ERA5MeanWaveDirDataLoader"]], "meshiphi.dataloaders.scalar.era5_mean_wave_direction.ERA5MeanWaveDirDataLoader": [[24, 3, 1, "", "import_data"]], "meshiphi.dataloaders.scalar.era5_sig_wave_height": [[23, 2, 1, "", "ERA5SigWaveHeightDataLoader"]], "meshiphi.dataloaders.scalar.era5_sig_wave_height.ERA5SigWaveHeightDataLoader": [[23, 3, 1, "", "import_data"]], "meshiphi.dataloaders.scalar.era5_wave_period": [[25, 2, 1, "", "ERA5WavePeriodDataLoader"]], "meshiphi.dataloaders.scalar.era5_wave_period.ERA5WavePeriodDataLoader": [[25, 3, 1, "", "import_data"]], "meshiphi.dataloaders.scalar.era5_wind_dir": [[26, 2, 1, "", "ERA5WindDirDataLoader"]], "meshiphi.dataloaders.scalar.era5_wind_dir.ERA5WindDirDataLoader": [[26, 3, 1, "", "import_data"]], "meshiphi.dataloaders.scalar.era5_wind_mag": [[27, 2, 1, "", "ERA5WindMagDataLoader"]], "meshiphi.dataloaders.scalar.era5_wind_mag.ERA5WindMagDataLoader": [[27, 3, 1, "", "import_data"]], "meshiphi.dataloaders.scalar.gebco": [[28, 2, 1, "", "GEBCODataLoader"]], "meshiphi.dataloaders.scalar.gebco.GEBCODataLoader": [[28, 3, 1, "", "import_data"]], "meshiphi.dataloaders.scalar.icenet": [[29, 2, 1, "", "IceNetDataLoader"]], "meshiphi.dataloaders.scalar.icenet.IceNetDataLoader": [[29, 3, 1, "", "import_data"]], "meshiphi.dataloaders.scalar.modis": [[30, 2, 1, "", "MODISDataLoader"]], "meshiphi.dataloaders.scalar.modis.MODISDataLoader": [[30, 3, 1, "", "import_data"]], "meshiphi.dataloaders.scalar.scalar_csv": [[31, 2, 1, "", "ScalarCSVDataLoader"]], "meshiphi.dataloaders.scalar.scalar_csv.ScalarCSVDataLoader": [[31, 3, 1, "", "import_data"]], "meshiphi.dataloaders.scalar.scalar_grf": [[32, 2, 1, "", "ScalarGRFDataLoader"]], "meshiphi.dataloaders.scalar.scalar_grf.ScalarGRFDataLoader": [[32, 3, 1, "", "add_default_params"], [32, 3, 1, "", "import_data"]], "meshiphi.dataloaders.scalar.shape": [[33, 2, 1, "", "ShapeDataLoader"]], "meshiphi.dataloaders.scalar.shape.ShapeDataLoader": [[33, 3, 1, "", "add_default_params"], [33, 3, 1, "", "gen_checkerboard"], [33, 3, 1, "", "gen_circle"], [33, 3, 1, "", "gen_gradient"], [33, 3, 1, "", "import_data"]], "meshiphi.dataloaders.vector": [[35, 0, 0, "-", "abstract_vector"], [36, 0, 0, "-", "baltic_current"], [37, 0, 0, "-", "duacs_current"], [38, 0, 0, "-", "era5_wave_direction_vector"], [39, 0, 0, "-", "era5_wind"], [40, 0, 0, "-", "north_sea_current"], [41, 0, 0, "-", "oras5_current"], [42, 0, 0, "-", "sose"], [43, 0, 0, "-", "vector_csv"], [44, 0, 0, "-", "vector_grf"]], "meshiphi.dataloaders.vector.abstract_vector": [[35, 2, 1, "", "VectorDataLoader"]], "meshiphi.dataloaders.vector.abstract_vector.VectorDataLoader": [[35, 3, 1, "", "__init__"], [35, 3, 1, "", "add_default_params"], [35, 3, 1, "", "add_mag_dir"], [35, 3, 1, "", "calc_curl"], [35, 3, 1, "", "calc_divergence"], [35, 3, 1, "", "calc_dmag"], [35, 3, 1, "", "calc_reynolds_number"], [35, 3, 1, "", "calculate_coverage"], [35, 3, 1, "", "downsample"], [35, 3, 1, "", "get_data_col_name"], [35, 3, 1, "", "get_data_col_name_list"], [35, 3, 1, "", "get_dp_from_coord"], [35, 3, 1, "", "get_hom_condition"], [35, 3, 1, "", "get_value"], [35, 3, 1, "", "import_data"], [35, 3, 1, "", "reproject"], [35, 3, 1, "", "set_data_col_name"], [35, 3, 1, "", "set_data_col_name_list"], [35, 3, 1, "", "trim_datapoints"]], "meshiphi.dataloaders.vector.abstract_vector.VectorDataLoader.self": [[35, 4, 1, "", "data"], [35, 4, 1, "", "data_name"]], "meshiphi.dataloaders.vector.baltic_current": [[36, 2, 1, "", "BalticCurrentDataLoader"]], "meshiphi.dataloaders.vector.baltic_current.BalticCurrentDataLoader": [[36, 3, 1, "", "import_data"]], "meshiphi.dataloaders.vector.duacs_current": [[37, 2, 1, "", "DuacsCurrentDataLoader"]], "meshiphi.dataloaders.vector.duacs_current.DuacsCurrentDataLoader": [[37, 3, 1, "", "import_data"]], "meshiphi.dataloaders.vector.era5_wave_direction_vector": [[38, 2, 1, "", "ERA5WaveDirectionLoader"]], "meshiphi.dataloaders.vector.era5_wave_direction_vector.ERA5WaveDirectionLoader": [[38, 3, 1, "", "import_data"]], "meshiphi.dataloaders.vector.era5_wind": [[39, 2, 1, "", "ERA5WindDataLoader"]], "meshiphi.dataloaders.vector.era5_wind.ERA5WindDataLoader": [[39, 3, 1, "", "import_data"]], "meshiphi.dataloaders.vector.north_sea_current": [[40, 2, 1, "", "NorthSeaCurrentDataLoader"]], "meshiphi.dataloaders.vector.north_sea_current.NorthSeaCurrentDataLoader": [[40, 3, 1, "", "import_data"]], "meshiphi.dataloaders.vector.oras5_current": [[41, 2, 1, "", "ORAS5CurrentDataLoader"]], "meshiphi.dataloaders.vector.oras5_current.ORAS5CurrentDataLoader": [[41, 3, 1, "", "import_data"]], "meshiphi.dataloaders.vector.sose": [[42, 2, 1, "", "SOSEDataLoader"]], "meshiphi.dataloaders.vector.sose.SOSEDataLoader": [[42, 3, 1, "", "import_data"]], "meshiphi.dataloaders.vector.vector_csv": [[43, 2, 1, "", "VectorCSVDataLoader"]], "meshiphi.dataloaders.vector.vector_csv.VectorCSVDataLoader": [[43, 3, 1, "", "import_data"]], "meshiphi.dataloaders.vector.vector_grf": [[44, 2, 1, "", "VectorGRFDataLoader"]], "meshiphi.dataloaders.vector.vector_grf.VectorGRFDataLoader": [[44, 3, 1, "", "add_default_params"], [44, 3, 1, "", "import_data"]], "meshiphi.mesh_generation": [[48, 0, 0, "-", "aggregated_cellbox"], [48, 0, 0, "-", "cellbox"], [48, 0, 0, "-", "environment_mesh"], [48, 0, 0, "-", "mesh_builder"], [48, 0, 0, "-", "metadata"], [48, 0, 0, "-", "neighbour_graph"]], "meshiphi.mesh_generation.aggregated_cellbox": [[48, 2, 1, "", "AggregatedCellBox"]], "meshiphi.mesh_generation.aggregated_cellbox.AggregatedCellBox": [[48, 3, 1, "", "__init__"], [48, 3, 1, "", "contains_point"], [48, 3, 1, "", "to_json"]], "meshiphi.mesh_generation.cellbox": [[48, 2, 1, "", "CellBox"]], "meshiphi.mesh_generation.cellbox.CellBox": [[48, 4, 1, "", "Bounds"], [48, 3, 1, "", "__init__"], [48, 3, 1, "", "aggregate"], [48, 4, 1, "", "id"], [48, 3, 1, "", "set_data_source"], [48, 3, 1, "", "set_parent"], [48, 3, 1, "", "should_split"], [48, 3, 1, "", "split"]], "meshiphi.mesh_generation.environment_mesh": [[48, 2, 1, "", "EnvironmentMesh"]], "meshiphi.mesh_generation.environment_mesh.EnvironmentMesh": [[48, 3, 1, "", "__init__"], [48, 4, 1, "", "agg_cellboxes"], [48, 4, 1, "", "bounds"], [48, 4, 1, "", "config"], [48, 3, 1, "", "load_from_json"], [48, 4, 1, "", "neighbour_graph"], [48, 3, 1, "", "save"], [48, 3, 1, "", "to_geojson"], [48, 3, 1, "", "to_json"], [48, 3, 1, "", "to_tif"], [48, 3, 1, "", "update_cellbox"]], "meshiphi.mesh_generation.mesh_builder": [[48, 2, 1, "", "MeshBuilder"]], "meshiphi.mesh_generation.mesh_builder.MeshBuilder": [[48, 3, 1, "", "__init__"], [48, 3, 1, "", "add_dataloader"], [48, 3, 1, "", "build_environmental_mesh"], [48, 3, 1, "", "split_and_replace"], [48, 3, 1, "", "split_to_depth"]], "meshiphi.mesh_generation.metadata": [[48, 2, 1, "", "Metadata"]], "meshiphi.mesh_generation.metadata.Metadata": [[48, 3, 1, "", "__init__"], [48, 4, 1, "", "data_loader"], [48, 4, 1, "", "splitting_conditions"], [48, 4, 1, "", "value_fill_type"]], "meshiphi.mesh_generation.neighbour_graph": [[48, 2, 1, "", "NeighbourGraph"]], "meshiphi.mesh_generation.neighbour_graph.NeighbourGraph": [[48, 3, 1, "", "get_neighbour_case"], [48, 3, 1, "", "initialise_neighbour_graph"], [48, 4, 1, "", "neighbour_graph"], [48, 3, 1, "", "update_neighbours"]], "meshiphi.mesh_plotting": [[52, 0, 0, "-", "mesh_plotter"]], "meshiphi.mesh_plotting.mesh_plotter": [[52, 2, 1, "", "MeshPlotter"]], "meshiphi.mesh_plotting.mesh_plotter.MeshPlotter": [[52, 3, 1, "", "__init__"], [52, 3, 1, "", "plot_bool"], [52, 3, 1, "", "plot_cmap"], [52, 3, 1, "", "save"]], "meshiphi.mesh_validation": [[50, 0, 0, "-", "mesh_validator"], [50, 0, 0, "-", "sampler"]], "meshiphi.mesh_validation.mesh_validator": [[50, 2, 1, "", "MeshValidator"]], "meshiphi.mesh_validation.mesh_validator.MeshValidator": [[50, 3, 1, "", "__init__"], [50, 4, 1, "", "env_mesh"], [50, 3, 1, "", "get_range_end"], [50, 3, 1, "", "get_value_from_data"], [50, 3, 1, "", "get_values_from_mesh"], [50, 4, 1, "", "mesh"], [50, 3, 1, "", "validate_mesh"], [50, 4, 1, "", "validation_length"]], "meshiphi.mesh_validation.sampler": [[50, 2, 1, "", "Sampler"]], "meshiphi.mesh_validation.sampler.Sampler": [[50, 3, 1, "", "__init__"], [50, 3, 1, "", "generate_samples"], [50, 4, 1, "", "number_of_samples"]]}, "objtypes": {"0": "py:module", "1": "py:function", "2": "py:class", "3": "py:method", "4": "py:attribute"}, "objnames": {"0": ["py", "module", "Python module"], "1": ["py", "function", "Python function"], "2": ["py", "class", "Python class"], "3": ["py", "method", "Python method"], "4": ["py", "attribute", "Python attribute"]}, "titleterms": {"welcom": 0, "meshiphi": 0, "manual": 0, "page": 0, "background": 1, "code": [1, 46], "overview": [1, 3, 15, 49], "structur": 1, "command": 2, "line": 2, "interfac": [2, 6], "create_mesh": 2, "export_mesh": 2, "rebuild_mesh": 2, "plot": [2, 52], "configur": [3, 4], "config": 3, "valid": [3, 50], "mesh": [4, 48, 49, 50, 51, 52], "construct": [4, 48, 49], "region": 4, "data": [4, 51], "sourc": 4, "split": 4, "ad": [5, 7], "new": [5, 7], "dataload": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45], "repositori": 5, "within": 5, "ipython": [5, 53], "notebook": [5, 53], "factori": 7, "exampl": [7, 14, 34, 45, 46], "object": 7, "abstract": [8, 14, 15, 16, 34, 35, 45], "look": 8, "up": 8, "tabl": 8, "densiti": 9, "lut": [10, 11, 14], "csv": [10, 31, 43], "geojson": 11, "scotland": 12, "ncmpa": 12, "thick": 13, "base": [14, 34, 45], "class": [14, 34, 45, 48], "implement": [14, 34, 45], "section": 15, "type": [15, 51], "scalar": [16, 31, 32, 34], "amsr": 17, "bsose": [18, 19], "depth": 18, "sea": [19, 20, 40], "ic": [19, 20], "baltic": [20, 36], "binari": 21, "grf": [21, 32, 44], "era5": [22, 23, 24, 25, 26, 27, 38, 39], "maximum": 22, "wave": [22, 23, 24, 25, 38], "height": [22, 23], "signific": 23, "mean": [24, 25], "direct": [24, 26, 38], "period": 25, "wind": [26, 27, 39], "magnitud": 27, "gebco": 28, "icenet": 29, "modi": 30, "shape": 33, "vector": [35, 43, 44, 45], "current": [36, 37, 40, 41, 42], "duac": 37, "north": 40, "oras5": 41, "sose": 42, "run": 46, "1": 46, "antarctica": 46, "process": 46, "all": 46, "stage": 46, "rout": [46, 51], "planner": 46, "2": 46, "dijkstra": 46, "v": 46, "smooth": 46, "path": [46, 51], "variat": 46, "vehicl": 46, "properti": 46, "instal": 47, "polarrout": 47, "gdal": 47, "window": 47, "linux": 47, "maco": 47, "meshbuild": 48, "environmentmesh": 48, "neighbourgraph": 48, "cellbox": [48, 51], "metadata": 48, "aggregatedcellbox": 48, "method": 49, "design": 49, "us": 49, "case": 49, "addit": 49, "sampler": 50, "output": 51, "The": 51, "json": 51, "file": 51, "neighbour_graph": 51, "vessel_mesh": 51, "waypoint": 51, "python": 53, "creat": 53, "digit": 53, "environ": 53}, "envversion": {"sphinx.domains.c": 2, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 6, "sphinx.domains.index": 1, "sphinx.domains.javascript": 2, "sphinx.domains.math": 2, "sphinx.domains.python": 3, "sphinx.domains.rst": 2, "sphinx.domains.std": 2, "sphinx.ext.todo": 2, "sphinx": 56}}) \ No newline at end of file +Search.setIndex({"docnames": ["index", "sections/Code_overview", "sections/Command_line_interface", "sections/Configuration/Configuration_overview", "sections/Configuration/Mesh_construction_config", "sections/Dataloaders/AddingDataloaders", "sections/Dataloaders/DataLoaderInterface", "sections/Dataloaders/Factory", "sections/Dataloaders/lut/abstractLUT", "sections/Dataloaders/lut/implemented/Density", "sections/Dataloaders/lut/implemented/LutCSV", "sections/Dataloaders/lut/implemented/LutGeoJSON", "sections/Dataloaders/lut/implemented/Scotland_NCMPA", "sections/Dataloaders/lut/implemented/Thickness", "sections/Dataloaders/lut/index", "sections/Dataloaders/overview", "sections/Dataloaders/scalar/abstractScalar", "sections/Dataloaders/scalar/implemented/AMSR", "sections/Dataloaders/scalar/implemented/BSOSEDepth", "sections/Dataloaders/scalar/implemented/BSOSESeaIce", "sections/Dataloaders/scalar/implemented/BalticSeaIce", "sections/Dataloaders/scalar/implemented/BinaryGRF", "sections/Dataloaders/scalar/implemented/ECMWFSigWaveHeight", "sections/Dataloaders/scalar/implemented/ERA5MaxWaveHeight", "sections/Dataloaders/scalar/implemented/ERA5SigWaveHeight", "sections/Dataloaders/scalar/implemented/ERA5WaveDirection", "sections/Dataloaders/scalar/implemented/ERA5WavePeriod", "sections/Dataloaders/scalar/implemented/ERA5WindDirection", "sections/Dataloaders/scalar/implemented/ERA5WindMagnitude", "sections/Dataloaders/scalar/implemented/GEBCO", "sections/Dataloaders/scalar/implemented/IceNet", "sections/Dataloaders/scalar/implemented/MODIS", "sections/Dataloaders/scalar/implemented/ScalarCSV", "sections/Dataloaders/scalar/implemented/ScalarGRF", "sections/Dataloaders/scalar/implemented/Shape", "sections/Dataloaders/scalar/implemented/visual_iced", "sections/Dataloaders/scalar/index", "sections/Dataloaders/vector/abstractVector", "sections/Dataloaders/vector/implemented/BalticCurrent", "sections/Dataloaders/vector/implemented/DUACS", "sections/Dataloaders/vector/implemented/ERA5WaveDirection", "sections/Dataloaders/vector/implemented/ERA5Wind", "sections/Dataloaders/vector/implemented/NorthSeaCurrent", "sections/Dataloaders/vector/implemented/ORAS5Current", "sections/Dataloaders/vector/implemented/SOSE", "sections/Dataloaders/vector/implemented/VectorCSV", "sections/Dataloaders/vector/implemented/VectorGRF", "sections/Dataloaders/vector/index", "sections/Installation", "sections/Mesh_Construction/Mesh_construction_classes", "sections/Mesh_Construction/Mesh_construction_overview", "sections/Mesh_Construction/Mesh_validation", "sections/Outputs", "sections/Plotting/mesh_plotting", "sections/ipython_notebooks"], "filenames": ["index.rst", "sections\\Code_overview.rst", "sections\\Command_line_interface.rst", "sections\\Configuration\\Configuration_overview.rst", "sections\\Configuration\\Mesh_construction_config.rst", "sections\\Dataloaders\\AddingDataloaders.rst", "sections\\Dataloaders\\DataLoaderInterface.rst", "sections\\Dataloaders\\Factory.rst", "sections\\Dataloaders\\lut\\abstractLUT.rst", "sections\\Dataloaders\\lut\\implemented\\Density.rst", "sections\\Dataloaders\\lut\\implemented\\LutCSV.rst", "sections\\Dataloaders\\lut\\implemented\\LutGeoJSON.rst", "sections\\Dataloaders\\lut\\implemented\\Scotland_NCMPA.rst", "sections\\Dataloaders\\lut\\implemented\\Thickness.rst", "sections\\Dataloaders\\lut\\index.rst", "sections\\Dataloaders\\overview.rst", "sections\\Dataloaders\\scalar\\abstractScalar.rst", "sections\\Dataloaders\\scalar\\implemented\\AMSR.rst", "sections\\Dataloaders\\scalar\\implemented\\BSOSEDepth.rst", "sections\\Dataloaders\\scalar\\implemented\\BSOSESeaIce.rst", "sections\\Dataloaders\\scalar\\implemented\\BalticSeaIce.rst", "sections\\Dataloaders\\scalar\\implemented\\BinaryGRF.rst", "sections\\Dataloaders\\scalar\\implemented\\ECMWFSigWaveHeight.rst", "sections\\Dataloaders\\scalar\\implemented\\ERA5MaxWaveHeight.rst", "sections\\Dataloaders\\scalar\\implemented\\ERA5SigWaveHeight.rst", "sections\\Dataloaders\\scalar\\implemented\\ERA5WaveDirection.rst", "sections\\Dataloaders\\scalar\\implemented\\ERA5WavePeriod.rst", "sections\\Dataloaders\\scalar\\implemented\\ERA5WindDirection.rst", "sections\\Dataloaders\\scalar\\implemented\\ERA5WindMagnitude.rst", "sections\\Dataloaders\\scalar\\implemented\\GEBCO.rst", "sections\\Dataloaders\\scalar\\implemented\\IceNet.rst", "sections\\Dataloaders\\scalar\\implemented\\MODIS.rst", "sections\\Dataloaders\\scalar\\implemented\\ScalarCSV.rst", "sections\\Dataloaders\\scalar\\implemented\\ScalarGRF.rst", "sections\\Dataloaders\\scalar\\implemented\\Shape.rst", "sections\\Dataloaders\\scalar\\implemented\\visual_iced.rst", "sections\\Dataloaders\\scalar\\index.rst", "sections\\Dataloaders\\vector\\abstractVector.rst", "sections\\Dataloaders\\vector\\implemented\\BalticCurrent.rst", "sections\\Dataloaders\\vector\\implemented\\DUACS.rst", "sections\\Dataloaders\\vector\\implemented\\ERA5WaveDirection.rst", "sections\\Dataloaders\\vector\\implemented\\ERA5Wind.rst", "sections\\Dataloaders\\vector\\implemented\\NorthSeaCurrent.rst", "sections\\Dataloaders\\vector\\implemented\\ORAS5Current.rst", "sections\\Dataloaders\\vector\\implemented\\SOSE.rst", "sections\\Dataloaders\\vector\\implemented\\VectorCSV.rst", "sections\\Dataloaders\\vector\\implemented\\VectorGRF.rst", "sections\\Dataloaders\\vector\\index.rst", "sections\\Installation.rst", "sections\\Mesh_Construction\\Mesh_construction_classes.rst", "sections\\Mesh_Construction\\Mesh_construction_overview.rst", "sections\\Mesh_Construction\\Mesh_validation.rst", "sections\\Outputs.rst", "sections\\Plotting\\mesh_plotting.rst", "sections\\ipython_notebooks.rst"], "titles": ["Welcome to the MeshiPhi Manual Pages", "4. Background", "3. Command Line Interface", "5. Configuration Overview", "5.1. Configuration - Mesh Construction", "7.6. Adding New Dataloaders", "7.1. Dataloader Interface", "7.2. Dataloader Factory", "7.5.1.1. Abstract Look Up Table Dataloader", "7.5.3.1. Density Dataloader", "7.5.3.2. LUT CSV Dataloader", "7.5.3.3. LUT GeoJSON Dataloader", "7.5.3.4. Scotland NCMPA Dataloader", "7.5.3.5. Thickness Dataloader", "7.5. LUT Dataloaders", "7. Dataloader Overview", "7.3.1.1. Abstract Scalar Dataloader", "7.3.3.1. AMSR Dataloader", "7.3.3.2. BSOSE Depth Dataloader", "7.3.3.3. BSOSE Sea Ice Dataloader", "7.3.3.4. Baltic Sea Ice Dataloader", "7.3.3.5. Binary GRF Dataloader", "7.3.3.6. ECMWFSigWaveHeight Dataloader", "7.3.3.7. ERA5 Maximum Wave Height Dataloader", "7.3.3.8. ERA5 Significant Wave Height Dataloader", "7.3.3.9. ERA5 Mean Wave Direction Dataloader", "7.3.3.10. ERA5 Mean Wave Period Dataloader", "7.3.3.11. ERA5 Wind Direction Dataloader", "7.3.3.12. ERA5 Wind Magnitude Dataloader", "7.3.3.13. GEBCO Dataloader", "7.3.3.14. IceNet Dataloader", "7.3.3.15. MODIS Dataloader", "7.3.3.16. Scalar CSV Dataloader", "7.3.3.17. Scalar GRF Dataloader", "7.3.3.18. Shape Dataloader", "7.3.3.19. Visual_iced Dataloader", "7.3. Scalar Dataloaders", "7.4.1.1. Abstract Vector Dataloader", "7.4.3.1. Baltic Currents Dataloader", "7.4.3.2. DUACS Currents Dataloader", "7.4.3.3. ERA5 Wave Direction Dataloader", "7.4.3.4. ERA5 Wind Dataloader", "7.4.3.5. North Sea Currents Dataloader", "7.4.3.6. ORAS5 Currents Dataloader", "7.4.3.7. SOSE Currents Dataloader", "7.4.3.8. Vector CSV Dataloader", "7.4.3.9. Vector GRF Dataloader", "7.4. Vector Dataloaders", "1. Installation", "8.4.1. Mesh Construction - Classes", "8. Methods - Mesh Construction", "8.4.2. Mesh Validation", "6. Outputs - Data Types", "9. Mesh Plotting", "2. Examples"], "terms": {"i": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 14, 15, 16, 17, 18, 19, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 54], "tool": [0, 1, 30], "discretis": [0, 1, 4], "environment": [0, 1, 4, 5, 15, 49], "data": [0, 1, 2, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 49, 50, 51, 54], "non": [0, 4, 49], "uniform": [0, 4, 49, 51], "resolut": [0, 1, 2, 4, 23, 24, 25, 26, 27, 28, 31, 34, 40, 41, 49, 54], "base": [0, 1, 2, 4, 5, 7, 9, 12, 13, 15, 17, 20, 49, 51], "varianc": 0, "thi": [0, 1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 13, 15, 16, 17, 18, 19, 21, 22, 32, 33, 34, 36, 37, 38, 40, 43, 44, 45, 47, 48, 49, 50, 51, 52, 54], "softwar": [0, 1, 2, 3, 48], "packag": [0, 2, 3, 48, 49, 54], "ha": [0, 2, 7, 9, 10, 11, 12, 13, 17, 18, 19, 20, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 38, 39, 40, 41, 42, 43, 44, 45, 46, 48, 49, 52], "been": [0, 2, 7, 15, 18, 19, 30, 44, 52], "develop": [0, 1, 30, 31, 35, 39, 54], "british": [0, 30, 35], "antarct": [0, 9, 13, 30, 35], "survei": [0, 30, 35], "ba": [0, 2, 54], "initi": [0, 4, 7, 8, 9, 10, 11, 12, 13, 15, 16, 17, 18, 19, 20, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 49, 50, 51], "part": [0, 39, 52], "rout": [0, 1, 2, 3, 4], "plan": [0, 1, 2, 3, 52], "research": [0, 17, 22, 30], "vessel": [0, 1, 2, 3, 49, 52], "rr": 0, "sir": 0, "david": 0, "attenborough": 0, "though": [0, 49, 54], "can": [0, 1, 2, 3, 7, 8, 10, 12, 15, 16, 17, 18, 19, 20, 22, 29, 31, 33, 34, 36, 37, 38, 39, 43, 44, 46, 47, 48, 49, 50, 52, 54], "appli": [0, 1, 4, 52], "ani": [0, 2, 4, 8, 10, 11, 16, 32, 37, 45, 49, 52], "geospati": [0, 49], "The": [0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 44, 45, 46, 47, 48, 49, 50, 54], "written": [0, 3, 7], "python": [0, 1, 3, 48, 54], "open": [0, 1, 3, 5, 14, 35, 36, 47, 49, 52, 54], "sourc": [0, 2, 7, 10, 11, 32, 34, 35, 36, 45, 47, 48, 49, 51, 54], "contain": [0, 2, 4, 8, 11, 15, 16, 21, 33, 34, 37, 46, 49, 51, 52], "limit": [0, 7, 8, 9, 10, 11, 12, 13, 16, 17, 18, 19, 20, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 49], "plot": [0, 1, 2, 4, 54], "function": [0, 4, 5, 8, 14, 15, 16, 17, 36, 37, 47, 49, 54], "which": [0, 1, 2, 4, 6, 15, 16, 18, 21, 35, 37, 40, 43, 49, 51, 52, 54], "describ": [0, 49, 50], "mesh": [0, 1, 2, 3, 5, 6, 7, 8, 10, 11, 14, 15, 16, 32, 34, 36, 37, 45, 47, 54], "section": [0, 1, 2, 3, 4, 48, 49, 50, 52, 54], "For": [0, 7, 15, 33, 46, 49, 50, 52], "more": [0, 14, 15, 16, 18, 19, 36, 37, 42, 44, 47, 49, 50, 52], "inform": [0, 1, 4, 23, 24, 25, 26, 27, 28, 31, 40, 41, 42, 49, 52], "project": [0, 2, 8, 15, 16, 18, 19, 36, 37, 44, 47, 49], "pleas": [0, 50], "visit": 0, "polarrout": [0, 2, 3, 15], "websit": [0, 18, 19, 23, 24, 25, 26, 27, 28, 30, 31, 39, 40, 41, 43, 44], "follow": [0, 1, 2, 4, 5, 7, 8, 15, 16, 33, 37, 46, 48, 49, 50, 52, 54], "our": [0, 1, 49], "github": [0, 2, 48], "repositori": [0, 48], "codebas": [0, 1], "ongo": 0, "yet": [0, 33, 46], "complet": [0, 8, 11, 16, 33, 34, 37, 46], "contact": 0, "content": 0, "background": 0, "code": [0, 2, 3, 6, 15, 49, 54], "overview": [0, 49, 52], "structur": [0, 3, 9, 49, 52], "instal": [0, 54], "gdal": 0, "ipython": [49, 54], "notebook": [49, 54], "creat": [0, 5, 7, 9, 12, 13, 14, 15, 33, 34, 36, 46, 47, 49], "digit": [0, 1, 2], "environ": [0, 2, 4, 48, 49, 50, 52], "command": [0, 3, 48, 54], "line": [0, 3, 4, 36, 47, 49, 54], "interfac": [0, 5, 15, 54], "create_mesh": [2, 54], "export_mesh": 0, "rebuild_mesh": 0, "configur": [0, 1, 2, 49, 50, 52, 54], "construct": [0, 1, 2, 3, 10, 11, 15, 32, 34, 45, 51, 52, 54], "config": [0, 2, 4, 5, 7, 8, 10, 11, 15, 16, 19, 21, 33, 34, 37, 46, 48, 49, 51, 52, 54], "valid": [0, 50], "output": [0, 1, 2, 15, 16, 35, 36, 37, 47, 54], "type": [0, 1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 12, 13, 16, 17, 18, 19, 20, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 49, 51], "json": [0, 2, 3, 4, 5, 7, 49, 54], "file": [0, 1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 47, 49, 51, 54], "vessel_mesh": 0, "dataload": [0, 1, 49, 52], "factori": [0, 5, 15, 34, 47], "scalar": [0, 4, 5, 7, 8, 10, 11, 14, 15, 17, 18, 19, 20, 21, 23, 24, 25, 26, 27, 28, 29, 30, 31, 34, 37, 46, 47], "vector": [0, 4, 7, 15, 33, 38, 39, 40, 41, 42, 43, 44, 49, 54], "lut": [0, 7, 8, 9, 12, 13, 15], "ad": [0, 4, 15, 49, 54], "new": [0, 14, 15, 18, 19, 36, 37, 44, 47, 49, 52], "method": [0, 1, 5, 6, 7, 8, 14, 15, 16, 34, 36, 37, 47, 49, 54], "design": [0, 10, 11, 32, 34, 45], "us": [0, 1, 2, 3, 4, 5, 7, 8, 9, 10, 11, 13, 14, 15, 16, 18, 19, 21, 23, 24, 25, 26, 27, 28, 29, 32, 33, 34, 37, 40, 41, 44, 45, 46, 47, 48, 49, 51, 52, 54], "case": [0, 4, 8, 15, 16, 37, 49, 52], "addit": [0, 1, 11, 17, 39, 52, 54], "exampl": [0, 1, 2, 3, 4, 5, 15, 49, 52], "run": [1, 2, 48, 49, 52, 54], "1": [4, 5, 13, 16, 20, 21, 31, 33, 34, 35, 36, 37, 49, 52], "antarctica": 48, "process": [1, 2, 3, 4, 15, 39, 51, 52], "all": [1, 3, 4, 6, 7, 8, 16, 23, 24, 25, 26, 27, 28, 36, 37, 40, 41, 47, 49, 51, 52], "stage": [1, 2, 3, 48, 52], "planner": [2, 4, 52], "2": [13, 16, 30, 31, 37, 49, 52], "dijkstra": [], "v": [2, 9, 40], "smooth": 1, "path": [2, 3, 49, 51], "variat": [], "vehicl": [1, 52], "properti": [9, 52], "we": [1, 3, 15, 35, 48, 49, 50], "present": [1, 23, 24, 25, 26, 27, 28, 40, 41], "an": [1, 2, 4, 5, 7, 8, 13, 14, 15, 18, 19, 23, 24, 25, 26, 27, 28, 30, 34, 36, 37, 40, 47, 48, 49, 50, 51, 52, 54], "autom": 1, "ic": [1, 9, 12, 13, 15, 17, 18, 30, 35, 36, 38, 43, 49, 52, 54], "strengthen": 1, "oper": [1, 4, 6, 8, 16, 20, 22, 37, 39, 48, 52], "polar": 1, "region": [1, 8, 10, 11, 13, 14, 49], "build": [1, 2, 4, 5, 49, 51], "underwat": 1, "long": [1, 4, 8, 15, 16, 17, 18, 19, 20, 21, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 49, 51, 52], "distanc": [1, 51, 52], "report": 1, "fox": 1, "et": [1, 9, 13, 30], "al": [1, 9, 13, 30], "2021": [1, 30], "start": [1, 4, 33, 34, 46, 49, 50, 52], "same": [1, 5, 8, 15, 16, 21, 37, 49, 54], "grid": [1, 4, 20, 23, 24, 25, 26, 27, 28, 39, 40, 41, 49], "approach": 1, "obtain": 1, "satisfi": [1, 4], "constraint": 1, "perform": [1, 2, 3, 4, 5, 7, 8, 10, 11, 16, 32, 37, 45, 49, 52], "ship": 1, "novel": 1, "result": [1, 49], "shorten": 1, "ensur": [1, 3, 15, 33], "great": 1, "circl": [1, 7, 34], "arc": 1, "where": [1, 2, 4, 8, 15, 16, 31, 37, 42, 49, 50, 52], "possibl": [1, 4, 8, 15, 16], "two": [1, 2, 7, 10, 15, 37, 46, 48, 49, 52], "effici": 1, "gener": [1, 4, 5, 6, 7, 8, 9, 13, 15, 16, 18, 19, 21, 23, 24, 25, 26, 27, 28, 29, 33, 34, 35, 37, 40, 41, 42, 44, 46, 49, 50, 51, 52], "standard": [1, 3, 14, 36, 47, 49, 52], "navig": 1, "solut": [1, 18, 19], "water": [1, 35], "optimis": 1, "around": [1, 12, 21], "area": [1, 4, 12, 15, 38], "domin": 1, "sea": [1, 9, 12, 13, 15, 17, 18, 30, 35, 36, 38, 39, 43, 47, 49, 54], "while": [1, 15], "have": [1, 4, 7, 8, 10, 15, 16, 36, 37, 47, 48, 51, 52], "focuss": 1, "ar": [1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 14, 15, 16, 20, 21, 22, 23, 24, 25, 26, 27, 28, 31, 33, 34, 35, 36, 37, 38, 40, 41, 42, 46, 47, 48, 49, 52], "also": [1, 2, 3, 4, 17, 37, 54], "applic": [1, 16, 37], "broader": [1, 22], "context": 1, "e": [1, 3, 4, 5, 15, 16, 37, 39, 47, 49], "g": [1, 3, 4, 5, 16, 37, 47, 49], "commerci": 1, "must": [1, 3, 4, 7, 8, 10, 14, 15, 16, 21, 33, 34, 36, 37, 46, 47], "respons": [1, 15], "chang": [1, 4, 8, 16, 37], "local": [1, 49], "weather": [1, 15, 22, 23, 24, 25, 26, 27, 28, 40, 41, 43], "condit": [1, 4, 6, 7, 8, 15, 16, 37, 49, 52], "outlin": [1, 3, 48, 49, 50], "manual": 1, "provid": [1, 2, 3, 7, 8, 11, 12, 14, 15, 16, 17, 18, 19, 20, 23, 24, 25, 26, 27, 28, 33, 34, 36, 37, 38, 39, 40, 41, 42, 43, 44, 46, 47, 49, 51, 54], "user": [1, 2, 5, 8, 14, 15, 16, 36, 37, 47, 52], "thei": [1, 3, 4, 15, 36, 47, 50], "need": [1, 5, 6, 7, 8, 14, 15, 16, 36, 37, 47, 54], "set": [1, 2, 4, 5, 7, 8, 11, 16, 21, 33, 34, 36, 37, 46, 47, 49, 52], "hope": 1, "suppli": [1, 3], "each": [1, 2, 3, 4, 5, 7, 8, 15, 16, 35, 37, 49, 50, 51, 52], "allow": [1, 2, 3, 4, 7, 16, 37, 48], "understand": [1, 17], "throughout": [1, 50], "toolkit": 1, "separ": [1, 3, 4, 5, 15, 47, 52], "broken": [1, 46], "down": [1, 15, 46, 52], "read": [1, 3, 5, 6, 7, 8, 10, 15, 17, 18, 19, 20, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 38, 39, 40, 41, 42, 43, 44, 45], "differ": [1, 14, 17, 21, 37, 39, 43, 47], "dataset": [1, 4, 8, 9, 10, 11, 12, 13, 15, 16, 17, 18, 19, 20, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47], "form": [1, 4, 6, 8, 16, 33, 34, 37, 46, 49, 52, 54], "input": [1, 3, 7, 49, 50], "should": [1, 4, 5, 8, 11, 15, 16, 37, 49, 51, 52, 54], "take": [1, 4, 10, 11, 13, 32, 40, 45, 50, 51, 52], "tip": 1, "pre": [1, 49], "your": [1, 15], "twin": 1, "In": [1, 3, 4, 6, 7, 15, 33, 35, 46, 48, 49], "class": [1, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15, 16, 17, 18, 19, 20, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 50, 51, 52], "represent": [1, 4, 49, 51, 52], "across": [1, 4], "defin": [1, 4, 5, 7, 8, 14, 15, 16, 17, 32, 33, 34, 36, 37, 45, 46, 47, 49, 52], "give": [1, 4, 39, 40], "dynam": [1, 39], "split": [1, 8, 15, 16, 49, 54], "finer": 1, "spatial": [1, 4, 15, 23, 24, 25, 26, 27, 28, 40, 41, 49, 51, 52], "vari": 1, "pipelin": [1, 52], "make": [1, 3, 4, 15, 52], "found": [1, 2, 3, 8, 16, 31, 52], "document": [1, 2, 3, 21, 49, 52, 54], "produc": [1, 2, 7, 15, 17, 20, 22, 23, 24, 25, 26, 27, 28, 33, 40, 41, 46, 49, 54], "main": [1, 4, 15, 49, 50], "seri": [1, 16, 37, 49], "interact": [1, 6, 50, 54], "map": [1, 13, 30, 35, 37, 49, 54], "static": [1, 7], "figur": [1, 4, 50], "featur": [1, 49, 52], "These": [1, 3, 4, 15, 35, 52], "later": 1, "caartographi": [], "cli": [2, 54], "entri": [2, 5, 7, 8, 16, 37, 43, 52, 54], "point": [2, 4, 16, 37, 49, 52, 54], "intend": 49, "success": [], "through": [2, 3, 6, 8, 49, 54], "from": [2, 3, 4, 5, 7, 8, 9, 10, 12, 13, 15, 16, 17, 18, 19, 20, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 47, 48, 49, 50, 52, 54], "collect": [2, 49], "model": [2, 3, 9, 18, 19, 42, 44, 49, 52], "posit": [2, 52], "argument": [2, 3], "A": [2, 4, 9, 13, 49, 50, 52, 54], "detail": [2, 4, 5, 14, 15, 36, 47, 49, 50], "how": [2, 4, 5, 6, 14, 15, 17, 23, 24, 25, 26, 27, 28, 36, 40, 41, 47, 49, 50, 54], "parsabl": [2, 49], "format": [2, 5, 8, 14, 15, 16, 18, 19, 36, 37, 44, 47, 49, 50, 52, 54], "requir": [2, 4, 5, 7, 8, 11, 14, 15, 16, 33, 34, 36, 37, 46, 47, 48], "option": [2, 3, 4, 5, 7, 8, 15, 48, 49], "verbos": 2, "log": [2, 36, 47], "o": [2, 48], "locat": [2, 4, 7, 49, 52], "return": [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, 17, 18, 19, 20, 21, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 49, 51, 52], "explain": 2, "onc": [2, 49, 52], "built": 2, "export": [2, 48, 49, 52], "other": [2, 4, 6, 16, 18, 19, 22, 29, 38, 39, 44, 49, 50], "system": [2, 4, 16, 30, 37, 39, 42, 43, 48], "gi": 2, "output_loc": 2, "output_format": 2, "save": [2, 8, 11, 14, 16, 36, 37, 46, 47, 49, 52, 54], "support": [2, 4, 8, 35, 49], "default": [2, 4, 7, 8, 10, 11, 16, 21, 33, 34, 36, 37, 46, 47, 49, 52], "geo": [2, 49, 51], "polygon": [2, 8, 10, 11, 13, 14, 49], "cell": [2, 4, 35, 49, 52], "geojson": [2, 12, 14, 15, 49, 52], "tif": [2, 49], "rasteris": 2, "format_conf": 2, "data_nam": [2, 4, 5, 6, 8, 10, 11, 16, 21, 33, 37, 46, 47, 49], "elev": [2, 4, 18, 29, 49, 52, 54], "sampling_resolut": [2, 49], "150": [2, 49], "3031": [2, 49], "color_conf": 2, "txt": 2, "variabl": [2, 4, 8, 9, 12, 13, 15, 16, 17, 18, 19, 20, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46], "name": [2, 4, 5, 7, 8, 10, 13, 15, 16, 21, 33, 37, 46, 47, 49, 52], "layer": [2, 38], "list": [2, 4, 7, 8, 10, 11, 16, 37, 49, 52, 54], "valu": [2, 3, 4, 6, 7, 8, 9, 10, 11, 13, 14, 15, 16, 17, 18, 19, 20, 21, 33, 34, 35, 36, 37, 38, 43, 46, 47, 49, 51, 52], "first": [2, 46, 48, 49, 52], "being": [2, 8, 11, 15, 16, 30, 33, 34, 36, 37, 46, 47, 49], "x": [2, 36, 37, 46, 47, 52], "second": [2, 46], "y": [2, 36, 37, 46, 47, 52], "string": [2, 3, 4, 10, 37, 47, 49, 51, 52], "epsg": [2, 4, 8, 15, 16, 36, 37, 47, 49], "color": [2, 49], "text": [2, 49], "scheme": 2, "when": [2, 4, 6, 8, 11, 14, 15, 16, 36, 37, 47, 48, 49, 52], "0": [2, 4, 5, 21, 33, 34, 35, 36, 46, 49, 52], "240": [2, 49], "250": [2, 49], "160": [2, 49], "30": [2, 4, 49], "230": [2, 49], "220": [2, 49], "170": [2, 49], "60": [2, 49], "100": [2, 4, 35, 49], "4": [2, 4, 13, 37, 49, 52], "column": [2, 8, 10, 11, 15, 16, 17, 21, 32, 33, 36, 37, 45, 46, 47, 49, 52], "per": [2, 13, 15, 21, 33, 46, 49], "correspond": [2, 37, 48, 49, 52], "red": [2, 49], "green": [2, 49], "blue": [2, 4, 49], "between": [2, 4, 16, 21, 34, 35, 37, 49, 51, 52], "255": [2, 49], "onli": [2, 4, 5, 6, 7, 11, 15, 17, 21, 35, 48], "specifi": [2, 4, 8, 10, 11, 13, 16, 19, 21, 33, 37, 51, 52], "you": [2, 5, 7, 48], "want": [2, 7, 8], "singl": [2, 4, 7, 8, 15, 16, 35], "rebuild": 2, "origin": [2, 37, 49, 52], "store": [2, 4, 6, 7, 8, 15, 16, 37, 47, 49], "within": [2, 4, 6, 7, 8, 9, 13, 15, 16, 17, 18, 19, 20, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 49, 51, 52, 54], "primarili": [2, 10, 11, 32, 34, 45], "debug": [2, 5, 34, 36, 47], "updat": [2, 17, 37, 48, 49], "old": [2, 37], "older": 2, "version": [2, 48], "reappli": 2, "simul": [2, 9, 12, 13, 30, 34], "were": [2, 9, 13, 37], "visualis": [2, 54], "geoplot": [0, 54], "librari": [2, 35], "relev": [2, 37, 52], "page": [2, 4, 5, 14, 15, 21, 33, 36, 46, 47, 48], "qgi": 2, "common": [2, 4, 15, 29, 48], "portion": [3, 4], "pass": [3, 7, 17, 49, 52], "script": 3, "directori": [2, 3], "descript": [3, 22, 51, 52], "At": [3, 7], "major": 3, "templat": [3, 15], "schema": 3, "check": [3, 4, 16, 37, 49], "correct": [3, 7, 34], "keyword": [3, 4, 11], "datatyp": 3, "": [2, 3, 4, 8, 15, 16, 17, 29, 31, 35, 37, 49, 50, 51, 52], "well": [3, 34], "waypoint": 3, "csv": [3, 11, 14, 15, 36, 47, 52], "rudimentari": 3, "sens": [3, 15], "starttim": [3, 4, 52], "befor": [3, 4, 5, 33, 51], "endtim": [3, 4], "meshiphi": [2, 3, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, 17, 18, 19, 20, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 49, 51, 52, 54], "config_valid": 3, "flexi_json_input": 3, "flexibl": [3, 7, 15], "If": [3, 4, 5, 8, 16, 19, 37, 49], "pars": [3, 8, 16], "assum": [3, 5, 37, 48], "dict": [3, 4, 6, 7, 8, 11, 13, 16, 17, 33, 34, 37, 46, 49, 51], "alreadi": [3, 36, 47], "load": [3, 5, 10, 11, 15, 17, 32, 33, 34, 35, 36, 45, 46, 47, 49, 52, 54], "paramet": [3, 4, 5, 7, 8, 9, 10, 11, 12, 13, 16, 17, 18, 19, 20, 21, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 49, 51, 54], "str": [3, 6, 7, 8, 16, 37, 49], "translat": [3, 7, 17], "rais": [3, 8, 16, 19, 37], "typeerror": 3, "neither": 3, "nor": 3, "wrong": [3, 36, 47], "dictionari": [3, 4, 5, 6, 7, 8, 11, 16, 17, 33, 34, 37, 46, 49], "validate_mesh_config": 3, "tri": 3, "filenam": 3, "incorrect": 3, "filenotfounderror": 3, "could": [3, 16, 37], "validationerror": 3, "malform": 3, "validate_route_config": 3, "validate_vessel_config": 3, "validate_waypoint": 3, "_summary_": 3, "pd": [3, 8, 9, 10, 11, 12, 13, 16, 30, 32, 33, 37, 45, 46, 52, 54], "datafram": [3, 8, 9, 10, 11, 12, 13, 14, 15, 16, 21, 30, 32, 33, 36, 37, 45, 46, 47, 52, 54], "_description_": 3, "assertionerror": [3, 8], "mesh_info": [4, 49], "latmin": 4, "65": 4, "latmax": 4, "longmin": 4, "70": [], "longmax": 4, "50": [4, 52], "2013": [], "03": [], "01": [4, 52], "14": [], "cellwidth": 4, "5": [4, 5, 7, 13, 21, 43, 49, 52], "cellheight": 4, "data_sourc": [4, 49], "loader": [4, 7, 21, 33, 46, 47, 49], "gebco": [7, 36, 52], "param": [4, 5, 7, 8, 9, 10, 11, 12, 13, 15, 16, 17, 18, 19, 20, 21, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 49, 51], "downsample_factor": [4, 16, 37], "datastor": [], "bathymetri": 15, "gebco_2022_n": [], "40": 4, "0_": [], "90": [], "0_w": [], "140": [], "0_e0": [], "nc": [], "value_fill_typ": [4, 49], "parent": [4, 49], "aggregate_typ": 4, "max": [4, 8, 16, 21, 33, 34, 37, 46, 49], "splitting_condit": [4, 5, 49], "threshold": [4, 5, 16, 21, 33, 37], "10": [4, 13, 33, 46, 48, 51], "upper_bound": [4, 5, 16], "lower_bound": [4, 5, 16], "amsr": [7, 36, 52], "folder": [7, 17], "sic": [4, 17, 18, 19, 20, 30, 31, 49, 52, 54], "amsr_south": [], "hemispher": [13, 17], "south": [49, 52], "35": [], "9": [5, 13, 48], "sose": [7, 18, 19, 47], "current": [4, 8, 15, 16, 17, 37, 47, 49, 54], "sose_curr": [], "sose_surface_velocity_6yearmean_2005": [], "2010": [], "uc": [4, 38, 39, 42, 43, 44, 46, 47], "vc": [4, 38, 39, 42, 43, 44, 46, 47], "curl": [4, 37], "04": 4, "thick": [4, 7, 9, 12, 14, 38, 52], "densiti": [4, 7, 13, 14, 15, 37, 52], "split_depth": [4, 49], "minimum_datapoint": [4, 49], "here": [4, 12, 17, 18, 19, 20, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 38, 39, 40, 41, 42, 43, 44], "dictat": [4, 15], "titl": [4, 10, 54], "three": [4, 15], "primari": 4, "discret": [4, 49, 50, 52], "definit": [4, 52], "bound": [4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, 17, 18, 19, 20, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 49, 51], "tempor": [4, 15, 23, 24, 25, 26, 27, 28, 35, 40, 41, 49], "interest": 4, "shape": [4, 8, 9, 10, 12, 14, 33, 36, 46], "box": [4, 49], "further": [4, 54], "given": [4, 13, 16, 35, 49, 52], "below": [4, 5, 16, 21, 36, 37, 47, 48, 50, 52], "77": [], "55": [], "120": [], "2017": [4, 52], "02": 4, "float": [4, 8, 13, 16, 37, 49, 51, 52], "degre": [4, 40, 52], "minimum": [4, 7, 16, 21, 33, 37, 46], "longitud": [4, 8, 15, 16, 37, 49, 52], "edg": [4, 8, 52], "maximum": [4, 21, 33, 36, 46, 49], "latitud": [4, 8, 15, 16, 37, 49, 52], "yyyi": [4, 49], "mm": [4, 49], "dd": [4, 49], "datetim": [4, 52], "time": [4, 7, 8, 15, 16, 32, 34, 36, 37, 39, 42, 45, 47, 49, 52], "averag": [4, 30, 37], "end": [4, 51, 52], "width": 4, "prior": [4, 54], "height": [4, 25, 26, 27, 28, 36, 38, 40, 41], "refer": [4, 16, 37, 50], "todai": 4, "3": [4, 13, 21, 33, 46, 48, 49, 52], "item": 4, "repres": [4, 35, 49, 51, 52], "add": [4, 5, 7, 15, 36, 37, 47, 48, 49, 51], "see": [4, 5, 21, 33, 46, 49, 50, 52], "abstractscalardataload": 4, "doc": [4, 14, 36, 47], "about": [4, 23, 24, 25, 26, 27, 28, 40, 41, 49, 50, 52], "avail": [2, 4, 7, 8, 9, 13, 16, 17, 18, 19, 23, 24, 25, 26, 27, 28, 29, 30, 37, 38, 39, 40, 41, 42, 43, 44, 52], "mai": [2, 4, 5, 6, 7, 15, 18, 19, 44, 47, 49, 52, 54], "includ": [4, 8, 15, 16, 22, 23, 24, 25, 26, 27, 28, 33, 34, 36, 37, 38, 40, 41, 43, 46, 47, 48, 49, 52, 54], "determin": [4, 6, 36, 37, 47, 49], "action": [4, 5, 7], "taken": [4, 9, 13, 15, 22], "cellbox": [4, 16, 34, 37, 51, 54], "either": [4, 8, 15, 16, 37, 47, 54], "impli": 4, "assign": [4, 10, 11, 49, 52], "zero": 4, "nan": [4, 8, 10, 11, 16, 37], "aggreg": [4, 6, 8, 16, 35, 37, 49, 51], "By": 4, "place": [4, 50, 51], "calcul": [4, 8, 16, 17, 37, 40, 49, 51], "mean": [4, 8, 16, 17, 18, 19, 36, 37, 38, 39, 40, 43, 44, 49], "min": [4, 8, 16, 21, 33, 34, 37, 46, 49], "count": [4, 8, 16, 37], "abov": [4, 16, 21, 37], "sub": 4, "divid": 4, "datapoint": [4, 7, 8, 15, 16, 21, 33, 34, 37, 46], "homogen": [4, 6, 7, 8, 16, 37, 49], "upperbound": [4, 16], "percentag": [4, 8, 16, 19, 37], "normalis": [4, 33], "deem": [4, 16], "greater": 4, "than": [4, 15, 16, 37], "lowerbound": [4, 16], "less": [4, 16, 37], "f": [4, 47, 49, 52, 54], "field": [4, 33, 37, 46], "order": [4, 15], "refin": 4, "done": 4, "select": [4, 7, 8, 16, 34, 37], "divis": 4, "whenev": 4, "size": [4, 16, 21, 33, 34, 37, 46], "inhomogen": 4, "respect": [4, 39], "specif": [4, 7, 8, 15, 16, 37, 49, 52], "characterist": [4, 37], "ocean": [4, 15, 17, 18, 19, 23, 24, 25, 26, 27, 28, 29, 39, 40, 41, 42, 43, 44, 49], "depth": [4, 36, 38, 42, 43, 49, 50], "insid": [4, 49, 50], "illustr": [4, 50], "graphic": [4, 49, 52], "decis": 4, "shown": [4, 5], "histogram": 4, "arbitrari": 4, "orang": 4, "denot": 4, "formula": 4, "black": 4, "ub": 4, "upper": [4, 8, 16, 37], "lb": 4, "lower": [4, 8, 16, 37], "To": [4, 7, 15, 52], "probabl": 4, "distribut": [4, 9, 13, 21, 33, 46, 48, 49, 54], "henc": 4, "under": [4, 5, 7, 51], "curv": 4, "decim": [4, 8, 16, 37, 51], "fraction": [4, 8, 16, 19, 37], "total": [4, 38, 52], "would": [4, 5, 14, 36, 47, 48, 51, 52], "show": [4, 6, 20, 54], "decid": 4, "clr": [4, 8, 16, 37, 49], "hom": [4, 16, 49], "het": [4, 8, 16, 37, 49], "There": [2, 4, 15], "fourth": 4, "trigger": [4, 37], "number": [4, 16, 21, 23, 24, 25, 26, 27, 28, 33, 37, 40, 41, 46, 49, 51], "do": [4, 5, 49], "extrem": 4, "alwai": [4, 15], "imagin": 4, "similar": [4, 47], "entir": [4, 31, 33], "both": [4, 7, 15, 22], "colour": 4, "meshbuild": [4, 5, 50, 54], "subject": 4, "abl": 4, "implement": [5, 6, 15, 22, 33, 46, 49], "object": [5, 8, 13, 15, 16, 17, 36, 37, 47, 49, 51, 52, 54], "workflow": 5, "choos": 5, "appropri": [5, 7], "import_data": [5, 8, 9, 10, 11, 12, 13, 16, 17, 18, 19, 20, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47], "add_default_param": [5, 8, 11, 15, 16, 17, 33, 34, 36, 37, 46, 47], "abstractscalar": [5, 6, 15, 36, 47], "abstractvector": [5, 6, 14, 15, 47], "py": [5, 7], "instruct": [5, 15, 23, 24, 25, 26, 27, 28, 40, 41, 48], "so": [5, 9, 13, 15, 36, 47, 48, 49], "after": [5, 49, 51, 52], "readi": 5, "go": 5, "It": [5, 10, 11, 17, 19, 21, 23, 24, 25, 26, 27, 28, 29, 32, 34, 40, 41, 44, 45, 48, 49, 50, 52], "purpos": 5, "__name__": 5, "__main__": 5, "test": [5, 10, 11, 15, 17, 32, 34, 45, 49], "its": [5, 22, 49, 51, 52, 54], "deploi": 5, "wish": 5, "modifi": 5, "repo": 5, "one": [5, 7, 8, 15, 16, 22, 37, 43, 48], "call": [5, 6, 7, 8, 16, 37, 50], "add_dataload": [5, 49], "re": 5, "work": [5, 14, 15, 18, 19, 36, 44, 47, 48], "out": [5, 8], "jupyt": [5, 49], "basic": 5, "step": [5, 16, 37, 48], "import": [5, 7, 8, 10, 11, 14, 16, 36, 37, 47, 49, 52, 54], "abstract": [5, 6, 11, 17, 33, 34, 46, 49], "abstract_scalar": [5, 16], "scalardataload": [5, 16, 36, 47, 49], "up": [5, 14, 15, 23, 24, 25, 26, 27, 28, 40, 41], "wai": [5, 49, 51], "exist": [5, 15, 37, 49], "mydataload": [5, 36, 47, 49], "def": [5, 7, 36, 47], "self": [5, 7, 8, 15, 16, 36, 37, 47, 49, 51], "len": [5, 36], "xr": [5, 8, 16, 17, 18, 19, 20, 23, 24, 25, 26, 27, 28, 29, 31, 36, 37, 38, 39, 40, 41, 42, 43, 44, 47], "open_dataset": [5, 36, 47], "els": [5, 36, 49], "open_mfdataset": [5, 36, 47], "trim": [5, 8, 15, 16, 37], "boundari": [5, 6, 7, 8, 9, 10, 11, 12, 13, 15, 16, 17, 18, 19, 20, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 49, 52], "trim_datapoint": [5, 8, 16, 37], "initialis": [5, 7, 8, 16, 37, 49, 54], "path_to_file_1": [5, 7], "path_to_file_2": [5, 7], "popul": 5, "mani": [5, 16, 37, 43, 49], "my_data": 5, "r": [5, 49, 52, 54], "fp": 5, "mesh_build": [5, 49, 54], "env_mesh": [5, 51], "build_environmental_mesh": [5, 49, 54], "from_json": 5, "builder": 5, "regener": 5, "modified_build": 5, "modified_mesh": 5, "get_hom_condit": [6, 8, 16, 37], "get_valu": [6, 8, 13, 15, 16, 37], "realist": [6, 33, 46], "dataloader_interfac": 6, "dataloaderinterfac": 6, "intern": [6, 8, 15, 16, 18, 19, 30, 37, 44], "retriev": [6, 7, 8, 15, 16, 37], "splitting_cond": [6, 8, 16, 37], "heterogen": 6, "agg_typ": [6, 8, 16, 37], "np": 6, "float64": 6, "off": 7, "get_dataload": 7, "veri": 7, "least": [7, 8], "those": [7, 49], "third": 7, "dataloader_requir": 7, "myscalardataload": 7, "mandatori": 7, "get": [7, 48, 49, 51], "kei": [7, 8, 14, 16, 17, 37, 47], "statement": 7, "dataloaderfactori": 7, "min_dp": [4, 7, 49], "myscalar": 7, "altern": [7, 15], "individu": [7, 37], "path_to_data_fil": 7, "path_to_fold": 7, "trail": 7, "quickli": 7, "scalar_csv": [7, 32], "scalar_grf": [4, 7, 33], "binary_grf": [7, 21], "bsose_s": [7, 52], "bsose_depth": [7, 18, 52], "baltic_s": [7, 52], "icenet": [7, 36, 52], "modi": [7, 35, 36, 52], "squar": [7, 34, 51], "gradient": [7, 34], "checkerboard": [7, 34], "vector_csv": [7, 45], "vector_grf": [4, 7, 46], "baltic_curr": [7, 38], "era5_wind": [7, 41, 52], "northsea_curr": 7, "oras5_curr": [7, 43], "duacs_curr": [7, 39], "era5_wave_height": 7, "era5_wave_direct": 7, "space": [7, 51], "int": [7, 13, 21, 33, 46, 49, 51], "translate_file_input": 7, "abstract_lut": 8, "lutdataload": [8, 14], "lookup": 8, "__init__": [8, 13, 15, 16, 33, 37, 46, 49, 51], "larg": [8, 15, 16, 23, 24, 25, 26, 27, 28, 37, 40, 41], "scale": [8, 16, 37], "downsampl": [8, 15, 16, 37], "reproject": [8, 15, 16, 17, 36, 37, 47], "renam": [8, 15, 16, 17, 18, 19, 20, 23, 24, 25, 26, 27, 28, 29, 30, 31, 36, 37, 38, 39, 40, 41, 42, 43, 44, 47], "scope": [8, 16, 37], "ingest": [8, 16, 18, 19, 37, 44], "uniqu": [8, 11, 16, 37], "upon": [8, 16, 37], "mercat": [8, 15, 16, 37], "4326": [4, 8, 15, 16, 36, 37, 47, 49], "geometri": [8, 10, 11, 13, 49, 52], "gpd": 8, "valueerror": [8, 16, 19, 37], "li": [8, 16], "overload": [8, 16, 37], "extra": [8, 16, 37], "attribut": [8, 11, 16, 17, 33, 34, 37, 46, 47, 49, 51, 52], "calculate_coverag": [8, 16, 37], "none": [8, 16, 21, 33, 37, 46, 49], "cover": [8, 16, 23, 24, 25, 26, 27, 28, 37, 40, 41], "compar": [8, 16, 37, 51], "against": [8, 16, 37, 51], "lookupt": 8, "get_data_col_nam": [8, 16, 37], "multipl": [8, 15, 16, 37], "t": [8, 16, 33, 36, 37, 47, 48], "datarang": [8, 16, 37], "analys": [8, 16, 37], "boolean": [8, 52], "true": [8, 16, 21, 37, 49, 52], "goe": [8, 49], "homogenieti": [8, 16, 37], "condtion": [8, 16, 37], "get_val_from_coord": 8, "lat": [4, 8, 15, 16, 17, 18, 19, 20, 21, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 49, 51, 52], "return_coord": [8, 16, 37], "fals": [4, 8, 16, 21, 33, 37, 54], "extract": [8, 16, 37, 49], "kwarg": [8, 16, 37], "coordin": [8, 9, 12, 13, 15, 16, 17, 18, 19, 20, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 49, 52], "search": [8, 16, 37], "flag": [8, 21, 33, 37], "whether": [8, 16, 37, 52], "coord": 8, "optionali": 8, "associ": [8, 10, 14, 49], "skipna": [8, 16, 37], "aggregation_typ": [8, 16, 37], "accept": [8, 16, 37], "median": [8, 16, 37], "std": [8, 16, 37], "bool": [8, 16, 37, 49], "propog": [8, 16, 37], "aggregated_valu": [8, 16, 37], "even": [8, 16, 37], "scratch": [8, 16, 37], "set_data_col_nam": [8, 16, 37], "new_nam": [8, 16, 37], "replac": [8, 16, 37, 49], "verify_data": 8, "verifi": 8, "multipolygon": 8, "paper": [9, 13], "worbi": [9, 13], "p": [9, 13], "took": 9, "princip": 9, "strength": 9, "buynitskii": 9, "k": 9, "download": [9, 12, 13, 17, 18, 19, 20, 22, 23, 24, 25, 26, 27, 28, 29, 31, 38, 39, 40, 41, 42, 43, 44], "densitydataload": 9, "scientif": [9, 12, 13], "literatur": [9, 12, 13], "date": [9, 12, 13], "density_df": 9, "cast": [10, 11, 15, 16, 32, 34, 37, 45, 54], "wa": [10, 11, 32, 34, 39, 42, 45, 52], "dummi": [10, 11, 32, 45], "As": [10, 18, 19, 32, 34, 44, 45, 52], "wkt": 10, "just": [10, 15], "lut_csv": 10, "lutcsv": 10, "outsid": [10, 11], "numpi": [10, 11, 51], "exclusion_df": [10, 11, 12], "lut_geojson": 11, "lutgeojson": 11, "over": [11, 16, 20], "regular": [11, 36, 47], "dummy_data": [11, 34], "scottish": 12, "govern": [12, 49], "natur": 12, "conserv": 12, "marin": [12, 15, 39], "protect": [12, 15], "scotland_ncmpa": 12, "scotlandncmpa": 12, "exclus": [12, 15], "zone": [12, 15], "thicknessdataload": 13, "value_dict": 13, "season": [13, 20, 30], "su": 13, "au": 13, "6": [4, 13, 30], "wi": 13, "7": [13, 22], "8": 13, "sp": 13, "11": 13, "12": [13, 52], "storag": [13, 49], "integ": [13, 51], "month": [13, 30], "account": 13, "jan": 13, "dec": 13, "thickness_df": 13, "look": [14, 15], "tabl": [14, 15], "hold": [14, 17, 36, 47], "most": [14, 36, 47], "manipul": [14, 16, 36, 37, 47, 54], "what": [14, 36, 47], "almost": [14, 47], "ident": [14, 47], "geopanda": [14, 15], "scotland": 14, "ncmpa": 14, "discuss": [15, 49], "transform": [15, 16, 37, 49, 52], "raw": 15, "interpret": 15, "reduc": [15, 16, 23, 24, 25, 26, 27, 28, 37, 40, 41], "comput": [15, 39], "resourc": [15, 29], "typic": 15, "netcdf": [15, 17, 18, 19, 20, 23, 24, 25, 26, 27, 28, 29, 30, 31, 36, 38, 39, 40, 41, 42, 43, 44, 47], "howev": 15, "whatev": 15, "panda": [15, 17, 36, 47, 52], "xarrai": [15, 34, 36, 47], "uml": [15, 50], "diagram": [15, 50], "subsystem": 15, "concentr": [15, 17, 18, 19, 20, 30, 35, 38, 49, 54], "etc": [15, 52], "error": 15, "cut": 15, "correctli": 15, "multi": [15, 39, 50], "dimension": 15, "wind": [4, 15, 36, 47, 52, 54], "compon": [15, 37, 38, 40, 46, 47], "dimens": [15, 34, 37, 51], "n": [15, 16, 37, 51, 52], "rigor": 15, "real": [4, 15, 33, 39, 46, 49], "prefer": 15, "localis": 15, "link": 15, "categori": 15, "generalis": 15, "via": [15, 52], "extens": [15, 18, 19], "dask": 15, "own": 15, "utilis": 15, "much": 15, "memori": 15, "consumpt": [15, 52], "shapefil": 15, "otherwis": 15, "extent": [16, 37], "easili": [16, 18, 19, 36, 37, 44, 47], "factor": [16, 37], "m": [16, 37], "bin": [16, 37, 48], "get_dp_from_coord": [16, 37], "Will": [16, 37], "chosen": [16, 37], "becaus": [16, 37], "bad": [16, 37], "data_point": [16, 51], "split_lock": 16, "proport": 16, "higher": [16, 48, 51], "ignor": [16, 37], "happen": [16, 37], "in_proj": [4, 16, 17, 36, 37, 47], "out_proj": [4, 16, 17, 36, 37, 47], "x_col": [4, 16, 17, 36, 37, 47], "y_col": [4, 16, 17, 36, 37, 47], "pyproj": [16, 17, 37], "cr": [16, 37], "final": [16, 37, 46, 49], "shouldn": [16, 37], "advanc": [17, 22], "microwav": 17, "scan": 17, "radiomet": 17, "publicli": [17, 18, 19, 29, 30, 43, 44], "earth": [17, 23, 24, 25, 26, 27, 28, 29, 31, 40, 41], "univers": 17, "bremen": 17, "standalon": 17, "independ": 17, "due": [17, 52], "issu": 17, "depend": 17, "caus": 17, "regress": [17, 49], "rectifi": 17, "soon": 17, "amsrdataload": 17, "turn": 17, "pair": 17, "drop": 17, "unnecessari": 17, "polar_stereograph": 17, "z": 17, "b": [18, 19], "biogeochem": [18, 19], "southern": [18, 19, 44], "state": [18, 19, 22, 44], "estim": [18, 19, 23, 24, 25, 26, 27, 28, 39, 40, 41, 43, 44], "host": [18, 19], "amongst": [18, 19, 29, 39, 44], "product": [18, 19, 23, 24, 25, 26, 27, 28, 31, 38, 39, 40, 41, 44, 48], "Their": [18, 42], "led": [18, 19, 30, 44], "mazloff": [18, 19, 44], "scripp": [18, 19, 44], "institut": [18, 19, 20, 22, 30, 38, 44], "oceanographi": [18, 19, 42, 44], "best": [18, 19, 44], "fit": [18, 19, 39, 44], "observ": [18, 19, 30, 44], "quantit": [18, 19, 44], "climatologi": [18, 19, 44], "note": [18, 19, 33, 44, 46, 49], "collat": [18, 19, 44], "bsosedepthdataload": 18, "bsose_sea_ic": 19, "bsoseseaicedataload": 19, "unit": [19, 40], "finnish": [20, 38], "meteorolog": [20, 22, 38], "fmi": [20, 38], "webpag": [20, 38], "servic": [20, 22, 39], "chart": [20, 29], "daili": [20, 38], "basi": 20, "dure": [20, 52], "km": 20, "baltic_sea_ic": 20, "balticseaicedataload": 20, "instead": 21, "consist": [21, 52], "land": [21, 23, 24, 25, 26, 27, 28, 40, 41, 52], "mask": [21, 33, 46], "seed": [4, 21, 33, 46], "random": [4, 21, 33, 46], "512": [4, 21, 33, 46], "axi": [21, 33, 46], "alpha": [4, 21, 33, 46], "power": [21, 33, 46], "law": [21, 33, 46], "momentum": [21, 33, 46], "famili": [23, 24, 25, 26, 27, 28, 40, 41], "european": [22, 23, 24, 25, 26, 27, 28, 39, 40, 41, 43], "centr": [22, 23, 24, 25, 26, 27, 28, 34, 40, 41, 42, 43], "medium": [22, 23, 24, 25, 26, 27, 28, 40, 41, 43], "rang": [22, 23, 24, 25, 26, 27, 28, 35, 40, 41, 43, 49, 51, 52], "forecast": [22, 23, 24, 25, 26, 27, 28, 30, 40, 41, 43], "ecmwf": [22, 23, 24, 25, 26, 27, 28, 40, 41, 43], "fifth": [23, 24, 25, 26, 27, 28, 40, 41], "atmospher": [23, 24, 25, 26, 27, 28, 40, 41], "reanalysi": [23, 24, 25, 26, 27, 28, 38, 39, 40, 41, 43], "global": [22, 23, 24, 25, 26, 27, 28, 39, 40, 41, 43, 49], "climat": [23, 24, 25, 26, 27, 28, 30, 40, 41], "period": [23, 24, 25, 27, 28, 36, 40, 41], "januari": [23, 24, 25, 26, 27, 28, 40, 41], "1950": [23, 24, 25, 26, 27, 28, 40, 41], "hourli": [23, 24, 25, 26, 27, 28, 40, 41], "30km": [23, 24, 25, 26, 27, 28, 40, 41], "resolv": [23, 24, 25, 26, 27, 28, 40, 41], "137": [23, 24, 25, 26, 27, 28, 40, 41], "level": [23, 24, 25, 26, 27, 28, 39, 40, 41], "surfac": [23, 24, 25, 26, 27, 28, 31, 38, 40, 41], "80km": [23, 24, 25, 26, 27, 28, 40, 41], "uncertainti": [23, 24, 25, 26, 27, 28, 40, 41], "era5_max_wave_height": 23, "era5maxwaveheightdataload": 23, "hmax": 23, "era5_sig_wave_height": 24, "era5sigwaveheightdataload": 24, "swh": 24, "era5_mean_wave_direct": 25, "era5meanwavedirdataload": 25, "mwd": [25, 40], "era5_wave_period": 26, "era5waveperioddataload": 26, "mwp": 26, "era5_wind_dir": 27, "era5winddirdataload": 27, "wave": [27, 28, 36, 47], "wind_dir": 27, "era5_wind_mag": 28, "era5windmagdataload": 28, "wind_mag": 28, "bathymetr": [29, 49], "scientist": 29, "gebcodataload": 29, "probabilist": 30, "deep": 30, "learn": 30, "team": 30, "alan": 30, "ture": 30, "andersson": 30, "train": [22, 30], "next": 30, "monthli": [30, 38, 43], "v1": 30, "v2": 30, "icenetdataload": 30, "moder": 31, "imag": [31, 35, 48, 49], "spectroradiomet": 31, "satellit": [31, 35, 39], "born": 31, "instrument": 31, "nasa": 31, "view": 31, "everi": [31, 38], "dai": 31, "acquir": 31, "36": 31, "spectral": 31, "band": 31, "group": 31, "wavelength": 31, "modisdataload": 31, "scalarcsvdataload": 32, "potenti": [32, 45], "head": [32, 45, 48], "gaussian": [4, 33, 46], "artifici": [33, 46], "somewhat": [33, 46], "world": [22, 33, 46, 49], "binari": [4, 33, 35, 36, 46, 48], "isn": 33, "cap": 33, "skew": 33, "outlier": 33, "randomis": 33, "multipli": [4, 33], "offset": [4, 33], "actual": [33, 51], "actual_min": 33, "actual_max": 33, "scalargrfdataload": 33, "known": 34, "shapedataload": 34, "gen_checkerboard": 34, "pattern": 34, "gen_circl": 34, "radiu": 34, "gen_gradi": 34, "direct": [34, 36, 37, 47, 49], "act": [34, 52], "like": [34, 49], "simpli": 34, "enact": 34, "data_xr": 34, "simpl": [36, 47], "my": [36, 47], "aren": [36, 47], "lon": [36, 47], "trim_data": [36, 47], "sometim": [36, 47], "constant": [36, 47], "super": [36, 47], "3412": [36, 47], "strictli": [36, 47], "speak": [36, 47], "necessari": [36, 47], "becom": [36, 47], "skip": [36, 47], "now": [36, 47], "bsose": [36, 42], "baltic": [36, 47], "grf": [36, 47, 54], "era5": [36, 47], "signific": 36, "magnitud": [36, 37, 46], "abstract_vector": 37, "vectordataload": [37, 47, 49], "add_mag_dir": 37, "easier": 37, "cartesian": 37, "data_name_list": 37, "_magnitud": 37, "_direct": 37, "calc_curl": 37, "collaps": 37, "collap": 37, "calc_diverg": 37, "diverg": 37, "div": 37, "calc_dmag": 37, "dmag": 37, "mag": 37, "mean_vector": 37, "calc_reynolds_numb": 37, "approxim": 37, "reynold": 37, "veloc": 37, "AND": 37, "viscos": 37, "OF": 37, "seawat": 37, "AT": 37, "c": 37, "WILL": 37, "minor": 37, "rework": 37, "TO": 37, "fluid": 37, "length": [37, 51], "append": 37, "comma": [37, 47], "seper": 37, "get_data_col_name_list": 37, "namesk": 37, "exceed": 37, "name_dict": 37, "old_nam": 37, "set_data_col_name_list": 37, "cmem": 38, "physic": 38, "whole": 38, "inclus": 38, "transit": 38, "north": [38, 40, 47, 49, 52], "hour": 38, "salin": 38, "temperatur": 38, "horizont": 38, "mix": 38, "bottom": 38, "balticcurrentdataload": 38, "copernicu": [38, 39], "mission": 39, "altimet": 39, "cne": 39, "cl": 39, "anomali": 39, "sla": 39, "twenti": 39, "year": 39, "1993": 39, "2012": 39, "optim": 39, "interpol": 39, "merg": 39, "l3": 39, "along": [39, 49, 52], "track": 39, "measur": 39, "absolut": 39, "topographi": 39, "geostroph": 39, "Near": 39, "duacscurrentdataload": 39, "deriv": 39, "come": [40, 49], "angl": [40, 52], "convert": [40, 49, 52], "u": 40, "era5_wave_direction_vector": 40, "era5wavedirectionload": 40, "uw": 40, "vw": 40, "era5winddataload": 41, "u10": [4, 41, 52], "v10": [4, 41, 52], "atlant": 42, "proudman": 42, "oceanograph": 42, "laboratori": 42, "coastal": 42, "polcom": 42, "uk": 42, "nation": 42, "liverpool": 42, "north_sea_curr": 42, "northseacurrentdataload": 42, "prepar": 43, "ocean5": 43, "analysi": 43, "compris": 43, "ensembl": 43, "member": [22, 43], "publish": 43, "catalogu": 43, "oras5currentdataload": 43, "sosedataload": 44, "vectorcsvdataload": 45, "vec_x": [4, 46], "vec_i": [4, 46], "vectorgrfdataload": 46, "itself": 47, "duac": 47, "oras5": 47, "googl": [], "colab": [], "full": [4, 52], "procedur": [], "shortli": [], "don": 48, "suggest": 48, "anaconda": 48, "http": [48, 52], "www": 48, "com": 48, "git": 48, "clone": 48, "setup": [], "pip": [48, 54], "tiff": [35, 48], "recommend": 48, "steer": 48, "clear": 48, "trivial": 48, "problem": 48, "With": 48, "said": 48, "variou": 48, "virtual": 48, "pipwin": 48, "easi": 48, "fiona": 48, "ubuntu": 48, "debian": 48, "sudo": 48, "apt": 48, "ppa": 48, "ubuntugi": 48, "libgdal": 48, "dev": 48, "cplus_include_path": 48, "usr": 48, "c_include_path": 48, "fedora": 48, "dnf": 48, "devel": 48, "homebrew": 48, "brew": 48, "modul": [49, 50], "behind": 49, "environmentalmesh": 49, "usag": 49, "execut": 49, "mesh_gener": [49, 54], "respos": 49, "lat_min": [4, 49], "lat_max": [4, 49], "long_min": [4, 49], "long_max": [4, 49], "start_tim": [4, 49], "end_tim": [4, 49], "cell_width": [4, 49], "cell_height": [4, 49], "longtitud": 49, "180": 49, "j_grid": 49, "java": 49, "cellgrid": 49, "evironment": 49, "nonunifrom": 49, "neighbour": [49, 52], "graph": 49, "split_and_replac": 49, "smaller": 49, "four": 49, "corner": 49, "surround": 49, "split_to_depth": 49, "until": 49, "reach": 49, "mutabl": 49, "environment_mesh": 49, "agg_cellbox": 49, "neighbour_graph": 49, "conatin": [49, 51], "classmethod": 49, "load_from_json": 49, "mesh_json": [49, 52, 54], "env": [49, 51], "ex": 49, "format_param": 49, "to_geojson": 49, "params_fil": 49, "doe": 49, "to_json": [49, 52, 54], "them": 49, "connect": 49, "togeth": 49, "cellgird": 49, "parseabl": 49, "adjac": [49, 52], "to_tif": 49, "geotif": 49, "folow": 49, "fuel": [49, 52], "pixel": 49, "2d": 49, "arrai": [49, 51], "sampl": [49, 51], "geotiff": 49, "espg": 49, "colour_conf": 49, "update_cellbox": 49, "index": [49, 52], "certain": [49, 50], "perf": 49, "metric": 49, "encod": [49, 52], "grid_width": 49, "relationship": 49, "id": [49, 52], "id_1": [49, 52], "id_n": [49, 52], "get_neighbour_cas": 49, "cellbox_a": 49, "cellbox_b": 49, "touch": 49, "destin": 49, "east": [49, 52], "west": [49, 52], "initialise_neighbour_graph": 49, "update_neighbour": 49, "cellbox_indx": 49, "new_neighbours_indx": 49, "remov": [49, 52], "neighbour_map": 49, "new_neighbour_indx": 49, "cellbox_index": 49, "hous": 49, "access": [49, 51, 52], "numer": [22, 49], "represnt": 49, "enabl": 49, "newli": 49, "logtitut": 49, "encapsul": 49, "set_data_sourc": 49, "spit": 49, "set_par": 49, "bigger": 49, "conain": 49, "got": 49, "should_split": 49, "stop_index": 49, "get_hom_cond": 49, "mixtur": 49, "stop": 49, "deprec": 49, "switch": 49, "breadth": 49, "start_id": 49, "represenst": 49, "usuallli": 49, "uniformli": 49, "among": 49, "data_load": [49, 52], "spliiting_condit": 49, "datasourc": 49, "assoc": 49, "indic": 49, "fill": [49, 51], "void": 49, "value_fill_tyep": 49, "aggregated_cellbox": 49, "agg_data": 49, "aggrgat": 49, "agg": 49, "contains_point": 49, "cx": [49, 52, 54], "cy": [49, 52], "dcx": [49, 52], "dcy": [49, 52], "agg_value_1": 49, "agg_value_n": 49, "cell_json": 49, "compos": 50, "seen": 50, "depict": 50, "sequenc": [50, 51], "client": 50, "build_environment_mesh": 50, "event": 50, "explan": 50, "todo": 51, "mesh_valid": 51, "meshvalid": 51, "mesh_config_fil": 51, "conf": 51, "vlaidat": 51, "validation_length": 51, "legnth": 51, "wil": 51, "incur": 51, "cost": 51, "cellboox": 51, "environmentmesh": 51, "get_range_end": 51, "clacul": 51, "get_value_from_data": 51, "get_values_from_mesh": 51, "find": 51, "arg": 51, "validate_mesh": 51, "number_of_sampl": 51, "agg_valu": 51, "rmse": 51, "actaul": 51, "d": 51, "sobol": 51, "highli": 51, "guarante": 51, "better": 51, "coverag": 51, "generate_sampl": 51, "equal": 51, "fall": 51, "stream": 52, "understood": 52, "value_1": 52, "value_n": 52, "centroid": 52, "dxy": 52, "longer": 52, "inaccess": 52, "remain": 52, "contract": 52, "vessel_perform": 52, "vessel_performance_model": 52, "vesselperformancemodel": 52, "vessel_config": 52, "vpm": 52, "model_access": 52, "model_perform": 52, "vessel_mesh_json": 52, "still": 52, "without": 52, "miss": 52, "sda": 52, "speed": 52, "travel": 52, "rate": 52, "consid": 52, "reason": 52, "shallow": 52, "enough": 52, "ext_ic": 52, "resist": 52, "forc": 52, "encount": 52, "rel": 52, "appar": 52, "piplin": 52, "waypoints_path": 52, "ot": 52, "falkland": 52, "rothera": 52, "52": 52, "6347222222": 52, "75": [4, 52], "26722": 52, "row": 52, "wgs84": 52, "waypoints_datafram": 52, "featurecollect": 52, "linestr": 52, "27": 52, "21694": 52, "07960297382266": 52, "619238882768894": 52, "hallei": 52, "traveltim": 52, "03531938671648596": 52, "050310986633880575": 52, "9648858923588642": 52, "3745886107069096": 52, "00": 52, "51": 52, "595036800": 52, "26": 52, "869276800": 52, "infor": 52, "org": 52, "meta": 52, "cumul": 52, "path_vari": 52, "utc": 52, "mesh_plot": [], "mesh_plott": [], "meshplott": [], "figscal": [], "matplotlib": [], "cartopi": [], "plot_bool": [], "value_nam": [], "plot_cmap": [], "colourmap": [], "termin": 54, "increas": 54, "alter": 54, "cg": 54, "dump": [], "plot_mesh": 0, "hetrogen": 2, "varieti": 2, "directli": 2, "optin": 2, "environment_config": [2, 4, 54], "grf_exampl": [2, 4, 54], "png": 2, "feild": 4, "16": 4, "dataloader_nam": 4, "44": 4, "850": 4, "1000": 4, "21": 4, "24": 22, "predict": 22, "co": 22, "commun": 22, "largest": 22, "supercomput": 22, "facil": 22, "archiv": 22, "strateg": 22, "activ": 22, "deliv": 22, "assist": 22, "wmo": 22, "programm": 22, "grib2": 22, "martin": 35, "roger": 35, "ai": 35, "lab": 35, "combin": 35, "sar": 35, "imageri": 35, "continu": 35, "ecmwfsigwaveheight": 36, "visual_": 36, "cd": 48, "bas_geoplot": 54, "mp": 54, "meshgrid": 54, "predefin": 54, "expect": 54}, "objects": {"meshiphi.config_validation": [[3, 0, 0, "-", "config_validator"]], "meshiphi.config_validation.config_validator": [[3, 1, 1, "", "flexi_json_input"], [3, 1, 1, "", "validate_mesh_config"], [3, 1, 1, "", "validate_route_config"], [3, 1, 1, "", "validate_vessel_config"], [3, 1, 1, "", "validate_waypoints"]], "meshiphi.dataloaders": [[6, 0, 0, "-", "dataloader_interface"], [7, 0, 0, "-", "factory"]], "meshiphi.dataloaders.dataloader_interface": [[6, 2, 1, "", "DataLoaderInterface"]], "meshiphi.dataloaders.dataloader_interface.DataLoaderInterface": [[6, 3, 1, "", "get_hom_condition"], [6, 3, 1, "", "get_value"]], "meshiphi.dataloaders.factory": [[7, 2, 1, "", "DataLoaderFactory"]], "meshiphi.dataloaders.factory.DataLoaderFactory": [[7, 3, 1, "", "get_dataloader"], [7, 3, 1, "", "translate_file_input"]], "meshiphi.dataloaders.lut": [[8, 0, 0, "-", "abstract_lut"], [9, 0, 0, "-", "density"], [10, 0, 0, "-", "lut_csv"], [11, 0, 0, "-", "lut_geojson"], [12, 0, 0, "-", "scotland_ncmpa"], [13, 0, 0, "-", "thickness"]], "meshiphi.dataloaders.lut.abstract_lut": [[8, 2, 1, "", "LutDataLoader"]], "meshiphi.dataloaders.lut.abstract_lut.LutDataLoader": [[8, 3, 1, "", "__init__"], [8, 3, 1, "", "add_default_params"], [8, 3, 1, "", "calculate_coverage"], [8, 3, 1, "", "downsample"], [8, 3, 1, "", "get_data_col_name"], [8, 3, 1, "", "get_hom_condition"], [8, 3, 1, "", "get_val_from_coord"], [8, 3, 1, "", "get_value"], [8, 3, 1, "", "import_data"], [8, 3, 1, "", "reproject"], [8, 3, 1, "", "set_data_col_name"], [8, 3, 1, "", "trim_datapoints"], [8, 3, 1, "", "verify_data"]], "meshiphi.dataloaders.lut.abstract_lut.LutDataLoader.self": [[8, 4, 1, "", "data"], [8, 4, 1, "", "data_name"]], "meshiphi.dataloaders.lut.density": [[9, 2, 1, "", "DensityDataLoader"]], "meshiphi.dataloaders.lut.density.DensityDataLoader": [[9, 3, 1, "", "import_data"]], "meshiphi.dataloaders.lut.lut_csv": [[10, 2, 1, "", "LutCSV"]], "meshiphi.dataloaders.lut.lut_csv.LutCSV": [[10, 3, 1, "", "import_data"]], "meshiphi.dataloaders.lut.lut_geojson": [[11, 2, 1, "", "LutGeoJSON"]], "meshiphi.dataloaders.lut.lut_geojson.LutGeoJSON": [[11, 3, 1, "", "add_default_params"], [11, 3, 1, "", "import_data"]], "meshiphi.dataloaders.lut.scotland_ncmpa": [[12, 2, 1, "", "ScotlandNCMPA"]], "meshiphi.dataloaders.lut.scotland_ncmpa.ScotlandNCMPA": [[12, 3, 1, "", "import_data"]], "meshiphi.dataloaders.lut.thickness": [[13, 2, 1, "", "ThicknessDataLoader"]], "meshiphi.dataloaders.lut.thickness.ThicknessDataLoader": [[13, 2, 1, "", "Region"], [13, 3, 1, "", "import_data"]], "meshiphi.dataloaders.lut.thickness.ThicknessDataLoader.Region": [[13, 3, 1, "", "__init__"], [13, 3, 1, "", "get_value"]], "meshiphi.dataloaders.scalar": [[16, 0, 0, "-", "abstract_scalar"], [17, 0, 0, "-", "amsr"], [20, 0, 0, "-", "baltic_sea_ice"], [18, 0, 0, "-", "bsose_depth"], [19, 0, 0, "-", "bsose_sea_ice"], [23, 0, 0, "-", "era5_max_wave_height"], [25, 0, 0, "-", "era5_mean_wave_direction"], [24, 0, 0, "-", "era5_sig_wave_height"], [26, 0, 0, "-", "era5_wave_period"], [27, 0, 0, "-", "era5_wind_dir"], [28, 0, 0, "-", "era5_wind_mag"], [29, 0, 0, "-", "gebco"], [30, 0, 0, "-", "icenet"], [31, 0, 0, "-", "modis"], [32, 0, 0, "-", "scalar_csv"], [33, 0, 0, "-", "scalar_grf"], [34, 0, 0, "-", "shape"]], "meshiphi.dataloaders.scalar.abstract_scalar": [[16, 2, 1, "", "ScalarDataLoader"]], "meshiphi.dataloaders.scalar.abstract_scalar.ScalarDataLoader": [[16, 3, 1, "", "__init__"], [16, 3, 1, "", "add_default_params"], [16, 3, 1, "", "calculate_coverage"], [16, 3, 1, "", "downsample"], [16, 3, 1, "", "get_data_col_name"], [16, 3, 1, "", "get_dp_from_coord"], [16, 3, 1, "", "get_hom_condition"], [16, 3, 1, "", "get_value"], [16, 3, 1, "", "import_data"], [16, 3, 1, "", "reproject"], [16, 3, 1, "", "set_data_col_name"], [16, 3, 1, "", "trim_datapoints"]], "meshiphi.dataloaders.scalar.abstract_scalar.ScalarDataLoader.self": [[16, 4, 1, "", "data"], [16, 4, 1, "", "data_name"]], "meshiphi.dataloaders.scalar.amsr": [[17, 2, 1, "", "AMSRDataLoader"]], "meshiphi.dataloaders.scalar.amsr.AMSRDataLoader": [[17, 3, 1, "", "add_default_params"], [17, 3, 1, "", "import_data"]], "meshiphi.dataloaders.scalar.baltic_sea_ice": [[20, 2, 1, "", "BalticSeaIceDataLoader"]], "meshiphi.dataloaders.scalar.baltic_sea_ice.BalticSeaIceDataLoader": [[20, 3, 1, "", "import_data"]], "meshiphi.dataloaders.scalar.bsose_depth": [[18, 2, 1, "", "BSOSEDepthDataLoader"]], "meshiphi.dataloaders.scalar.bsose_depth.BSOSEDepthDataLoader": [[18, 3, 1, "", "import_data"]], "meshiphi.dataloaders.scalar.bsose_sea_ice": [[19, 2, 1, "", "BSOSESeaIceDataLoader"]], "meshiphi.dataloaders.scalar.bsose_sea_ice.BSOSESeaIceDataLoader": [[19, 3, 1, "", "import_data"]], "meshiphi.dataloaders.scalar.era5_max_wave_height": [[23, 2, 1, "", "ERA5MaxWaveHeightDataLoader"]], "meshiphi.dataloaders.scalar.era5_max_wave_height.ERA5MaxWaveHeightDataLoader": [[23, 3, 1, "", "import_data"]], "meshiphi.dataloaders.scalar.era5_mean_wave_direction": [[25, 2, 1, "", "ERA5MeanWaveDirDataLoader"]], "meshiphi.dataloaders.scalar.era5_mean_wave_direction.ERA5MeanWaveDirDataLoader": [[25, 3, 1, "", "import_data"]], "meshiphi.dataloaders.scalar.era5_sig_wave_height": [[24, 2, 1, "", "ERA5SigWaveHeightDataLoader"]], "meshiphi.dataloaders.scalar.era5_sig_wave_height.ERA5SigWaveHeightDataLoader": [[24, 3, 1, "", "import_data"]], "meshiphi.dataloaders.scalar.era5_wave_period": [[26, 2, 1, "", "ERA5WavePeriodDataLoader"]], "meshiphi.dataloaders.scalar.era5_wave_period.ERA5WavePeriodDataLoader": [[26, 3, 1, "", "import_data"]], "meshiphi.dataloaders.scalar.era5_wind_dir": [[27, 2, 1, "", "ERA5WindDirDataLoader"]], "meshiphi.dataloaders.scalar.era5_wind_dir.ERA5WindDirDataLoader": [[27, 3, 1, "", "import_data"]], "meshiphi.dataloaders.scalar.era5_wind_mag": [[28, 2, 1, "", "ERA5WindMagDataLoader"]], "meshiphi.dataloaders.scalar.era5_wind_mag.ERA5WindMagDataLoader": [[28, 3, 1, "", "import_data"]], "meshiphi.dataloaders.scalar.gebco": [[29, 2, 1, "", "GEBCODataLoader"]], "meshiphi.dataloaders.scalar.gebco.GEBCODataLoader": [[29, 3, 1, "", "import_data"]], "meshiphi.dataloaders.scalar.icenet": [[30, 2, 1, "", "IceNetDataLoader"]], "meshiphi.dataloaders.scalar.icenet.IceNetDataLoader": [[30, 3, 1, "", "import_data"]], "meshiphi.dataloaders.scalar.modis": [[31, 2, 1, "", "MODISDataLoader"]], "meshiphi.dataloaders.scalar.modis.MODISDataLoader": [[31, 3, 1, "", "import_data"]], "meshiphi.dataloaders.scalar.scalar_csv": [[32, 2, 1, "", "ScalarCSVDataLoader"]], "meshiphi.dataloaders.scalar.scalar_csv.ScalarCSVDataLoader": [[32, 3, 1, "", "import_data"]], "meshiphi.dataloaders.scalar.scalar_grf": [[33, 2, 1, "", "ScalarGRFDataLoader"]], "meshiphi.dataloaders.scalar.scalar_grf.ScalarGRFDataLoader": [[33, 3, 1, "", "add_default_params"], [33, 3, 1, "", "import_data"]], "meshiphi.dataloaders.scalar.shape": [[34, 2, 1, "", "ShapeDataLoader"]], "meshiphi.dataloaders.scalar.shape.ShapeDataLoader": [[34, 3, 1, "", "add_default_params"], [34, 3, 1, "", "gen_checkerboard"], [34, 3, 1, "", "gen_circle"], [34, 3, 1, "", "gen_gradient"], [34, 3, 1, "", "import_data"]], "meshiphi.dataloaders.vector": [[37, 0, 0, "-", "abstract_vector"], [38, 0, 0, "-", "baltic_current"], [39, 0, 0, "-", "duacs_current"], [40, 0, 0, "-", "era5_wave_direction_vector"], [41, 0, 0, "-", "era5_wind"], [42, 0, 0, "-", "north_sea_current"], [43, 0, 0, "-", "oras5_current"], [44, 0, 0, "-", "sose"], [45, 0, 0, "-", "vector_csv"], [46, 0, 0, "-", "vector_grf"]], "meshiphi.dataloaders.vector.abstract_vector": [[37, 2, 1, "", "VectorDataLoader"]], "meshiphi.dataloaders.vector.abstract_vector.VectorDataLoader": [[37, 3, 1, "", "__init__"], [37, 3, 1, "", "add_default_params"], [37, 3, 1, "", "add_mag_dir"], [37, 3, 1, "", "calc_curl"], [37, 3, 1, "", "calc_divergence"], [37, 3, 1, "", "calc_dmag"], [37, 3, 1, "", "calc_reynolds_number"], [37, 3, 1, "", "calculate_coverage"], [37, 3, 1, "", "downsample"], [37, 3, 1, "", "get_data_col_name"], [37, 3, 1, "", "get_data_col_name_list"], [37, 3, 1, "", "get_dp_from_coord"], [37, 3, 1, "", "get_hom_condition"], [37, 3, 1, "", "get_value"], [37, 3, 1, "", "import_data"], [37, 3, 1, "", "reproject"], [37, 3, 1, "", "set_data_col_name"], [37, 3, 1, "", "set_data_col_name_list"], [37, 3, 1, "", "trim_datapoints"]], "meshiphi.dataloaders.vector.abstract_vector.VectorDataLoader.self": [[37, 4, 1, "", "data"], [37, 4, 1, "", "data_name"]], "meshiphi.dataloaders.vector.baltic_current": [[38, 2, 1, "", "BalticCurrentDataLoader"]], "meshiphi.dataloaders.vector.baltic_current.BalticCurrentDataLoader": [[38, 3, 1, "", "import_data"]], "meshiphi.dataloaders.vector.duacs_current": [[39, 2, 1, "", "DuacsCurrentDataLoader"]], "meshiphi.dataloaders.vector.duacs_current.DuacsCurrentDataLoader": [[39, 3, 1, "", "import_data"]], "meshiphi.dataloaders.vector.era5_wave_direction_vector": [[40, 2, 1, "", "ERA5WaveDirectionLoader"]], "meshiphi.dataloaders.vector.era5_wave_direction_vector.ERA5WaveDirectionLoader": [[40, 3, 1, "", "import_data"]], "meshiphi.dataloaders.vector.era5_wind": [[41, 2, 1, "", "ERA5WindDataLoader"]], "meshiphi.dataloaders.vector.era5_wind.ERA5WindDataLoader": [[41, 3, 1, "", "import_data"]], "meshiphi.dataloaders.vector.north_sea_current": [[42, 2, 1, "", "NorthSeaCurrentDataLoader"]], "meshiphi.dataloaders.vector.north_sea_current.NorthSeaCurrentDataLoader": [[42, 3, 1, "", "import_data"]], "meshiphi.dataloaders.vector.oras5_current": [[43, 2, 1, "", "ORAS5CurrentDataLoader"]], "meshiphi.dataloaders.vector.oras5_current.ORAS5CurrentDataLoader": [[43, 3, 1, "", "import_data"]], "meshiphi.dataloaders.vector.sose": [[44, 2, 1, "", "SOSEDataLoader"]], "meshiphi.dataloaders.vector.sose.SOSEDataLoader": [[44, 3, 1, "", "import_data"]], "meshiphi.dataloaders.vector.vector_csv": [[45, 2, 1, "", "VectorCSVDataLoader"]], "meshiphi.dataloaders.vector.vector_csv.VectorCSVDataLoader": [[45, 3, 1, "", "import_data"]], "meshiphi.dataloaders.vector.vector_grf": [[46, 2, 1, "", "VectorGRFDataLoader"]], "meshiphi.dataloaders.vector.vector_grf.VectorGRFDataLoader": [[46, 3, 1, "", "add_default_params"], [46, 3, 1, "", "import_data"]], "meshiphi.mesh_generation": [[49, 0, 0, "-", "aggregated_cellbox"], [49, 0, 0, "-", "cellbox"], [49, 0, 0, "-", "environment_mesh"], [49, 0, 0, "-", "mesh_builder"], [49, 0, 0, "-", "metadata"], [49, 0, 0, "-", "neighbour_graph"]], "meshiphi.mesh_generation.aggregated_cellbox": [[49, 2, 1, "", "AggregatedCellBox"]], "meshiphi.mesh_generation.aggregated_cellbox.AggregatedCellBox": [[49, 3, 1, "", "__init__"], [49, 3, 1, "", "contains_point"], [49, 3, 1, "", "to_json"]], "meshiphi.mesh_generation.cellbox": [[49, 2, 1, "", "CellBox"]], "meshiphi.mesh_generation.cellbox.CellBox": [[49, 4, 1, "", "Bounds"], [49, 3, 1, "", "__init__"], [49, 3, 1, "", "aggregate"], [49, 4, 1, "", "id"], [49, 3, 1, "", "set_data_source"], [49, 3, 1, "", "set_parent"], [49, 3, 1, "", "should_split"], [49, 3, 1, "", "split"]], "meshiphi.mesh_generation.environment_mesh": [[49, 2, 1, "", "EnvironmentMesh"]], "meshiphi.mesh_generation.environment_mesh.EnvironmentMesh": [[49, 3, 1, "", "__init__"], [49, 4, 1, "", "agg_cellboxes"], [49, 4, 1, "", "bounds"], [49, 4, 1, "", "config"], [49, 3, 1, "", "load_from_json"], [49, 4, 1, "", "neighbour_graph"], [49, 3, 1, "", "save"], [49, 3, 1, "", "to_geojson"], [49, 3, 1, "", "to_json"], [49, 3, 1, "", "to_tif"], [49, 3, 1, "", "update_cellbox"]], "meshiphi.mesh_generation.mesh_builder": [[49, 2, 1, "", "MeshBuilder"]], "meshiphi.mesh_generation.mesh_builder.MeshBuilder": [[49, 3, 1, "", "__init__"], [49, 3, 1, "", "add_dataloader"], [49, 3, 1, "", "build_environmental_mesh"], [49, 3, 1, "", "split_and_replace"], [49, 3, 1, "", "split_to_depth"]], "meshiphi.mesh_generation.metadata": [[49, 2, 1, "", "Metadata"]], "meshiphi.mesh_generation.metadata.Metadata": [[49, 3, 1, "", "__init__"], [49, 4, 1, "", "data_loader"], [49, 4, 1, "", "splitting_conditions"], [49, 4, 1, "", "value_fill_type"]], "meshiphi.mesh_generation.neighbour_graph": [[49, 2, 1, "", "NeighbourGraph"]], "meshiphi.mesh_generation.neighbour_graph.NeighbourGraph": [[49, 3, 1, "", "get_neighbour_case"], [49, 3, 1, "", "initialise_neighbour_graph"], [49, 4, 1, "", "neighbour_graph"], [49, 3, 1, "", "update_neighbours"]], "meshiphi.mesh_validation": [[51, 0, 0, "-", "mesh_validator"], [51, 0, 0, "-", "sampler"]], "meshiphi.mesh_validation.mesh_validator": [[51, 2, 1, "", "MeshValidator"]], "meshiphi.mesh_validation.mesh_validator.MeshValidator": [[51, 3, 1, "", "__init__"], [51, 4, 1, "", "env_mesh"], [51, 3, 1, "", "get_range_end"], [51, 3, 1, "", "get_value_from_data"], [51, 3, 1, "", "get_values_from_mesh"], [51, 4, 1, "", "mesh"], [51, 3, 1, "", "validate_mesh"], [51, 4, 1, "", "validation_length"]], "meshiphi.mesh_validation.sampler": [[51, 2, 1, "", "Sampler"]], "meshiphi.mesh_validation.sampler.Sampler": [[51, 3, 1, "", "__init__"], [51, 3, 1, "", "generate_samples"], [51, 4, 1, "", "number_of_samples"]]}, "objtypes": {"0": "py:module", "1": "py:function", "2": "py:class", "3": "py:method", "4": "py:attribute"}, "objnames": {"0": ["py", "module", "Python module"], "1": ["py", "function", "Python function"], "2": ["py", "class", "Python class"], "3": ["py", "method", "Python method"], "4": ["py", "attribute", "Python attribute"]}, "titleterms": {"welcom": 0, "meshiphi": [0, 48], "manual": 0, "page": 0, "background": 1, "code": 1, "overview": [1, 3, 15, 50], "structur": 1, "command": 2, "line": 2, "interfac": [2, 6], "create_mesh": [], "export_mesh": 2, "rebuild_mesh": 2, "plot": 53, "configur": [3, 4], "config": 3, "valid": [3, 51], "mesh": [4, 49, 50, 51, 52, 53], "construct": [4, 49, 50], "region": 4, "data": [4, 52], "sourc": 4, "split": 4, "ad": [5, 7], "new": [5, 7], "dataload": [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47], "repositori": 5, "within": 5, "ipython": 5, "notebook": 5, "factori": 7, "exampl": [7, 14, 36, 47, 54], "object": 7, "abstract": [8, 14, 15, 16, 36, 37, 47], "look": 8, "up": 8, "tabl": 8, "densiti": 9, "lut": [10, 11, 14], "csv": [10, 32, 45], "geojson": 11, "scotland": 12, "ncmpa": 12, "thick": 13, "base": [14, 36, 47], "class": [14, 36, 47, 49], "implement": [14, 36, 47], "section": 15, "type": [15, 52], "scalar": [16, 32, 33, 36], "amsr": 17, "bsose": [18, 19], "depth": 18, "sea": [19, 20, 42], "ic": [19, 20], "baltic": [20, 38], "binari": 21, "grf": [21, 33, 46], "era5": [23, 24, 25, 26, 27, 28, 40, 41], "maximum": 23, "wave": [23, 24, 25, 26, 40], "height": [23, 24], "signific": 24, "mean": [25, 26], "direct": [25, 27, 40], "period": 26, "wind": [27, 28, 41], "magnitud": 28, "gebco": 29, "icenet": 30, "modi": 31, "shape": 34, "vector": [37, 45, 46, 47], "current": [38, 39, 42, 43, 44], "duac": 39, "north": 42, "oras5": 43, "sose": 44, "run": [], "1": [], "antarctica": [], "process": [], "all": [], "stage": [], "rout": 52, "planner": [], "2": [], "dijkstra": [], "v": [], "smooth": [], "path": 52, "variat": [], "vehicl": [], "properti": [], "instal": 48, "polarrout": [], "gdal": 48, "window": 48, "linux": 48, "maco": 48, "meshbuild": 49, "environmentmesh": 49, "neighbourgraph": 49, "cellbox": [49, 52], "metadata": 49, "aggregatedcellbox": 49, "method": 50, "design": 50, "us": 50, "case": 50, "addit": 50, "sampler": 51, "output": 52, "The": 52, "json": 52, "file": 52, "neighbour_graph": 52, "vessel_mesh": 52, "waypoint": 52, "python": [], "creat": 54, "digit": 54, "environ": 54, "plot_mesh": 2, "geoplot": 2, "ecmwfsigwaveheight": 22, "visual_": 35}, "envversion": {"sphinx.domains.c": 2, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 6, "sphinx.domains.index": 1, "sphinx.domains.javascript": 2, "sphinx.domains.math": 2, "sphinx.domains.python": 3, "sphinx.domains.rst": 2, "sphinx.domains.std": 2, "sphinx.ext.todo": 2, "sphinx": 56}}) \ No newline at end of file diff --git a/docs/html/sections/Dataloaders/Factory.html b/docs/html/sections/Dataloaders/Factory.html index 26b0304b..f1548bd2 100644 --- a/docs/html/sections/Dataloaders/Factory.html +++ b/docs/html/sections/Dataloaders/Factory.html @@ -45,10 +45,10 @@ diff --git a/docs/html/sections/Dataloaders/overview.html b/docs/html/sections/Dataloaders/overview.html index 9d5ddeb0..5cf3ac42 100644 --- a/docs/html/sections/Dataloaders/overview.html +++ b/docs/html/sections/Dataloaders/overview.html @@ -45,10 +45,10 @@ diff --git a/docs/html/sections/Dataloaders/scalar/abstractScalar.html b/docs/html/sections/Dataloaders/scalar/abstractScalar.html index f22be1ba..9b72a853 100644 --- a/docs/html/sections/Dataloaders/scalar/abstractScalar.html +++ b/docs/html/sections/Dataloaders/scalar/abstractScalar.html @@ -45,10 +45,10 @@ diff --git a/docs/html/sections/Dataloaders/scalar/implemented/AMSR.html b/docs/html/sections/Dataloaders/scalar/implemented/AMSR.html index 414e06df..15c42266 100644 --- a/docs/html/sections/Dataloaders/scalar/implemented/AMSR.html +++ b/docs/html/sections/Dataloaders/scalar/implemented/AMSR.html @@ -45,10 +45,10 @@ diff --git a/docs/html/sections/Dataloaders/scalar/implemented/BSOSEDepth.html b/docs/html/sections/Dataloaders/scalar/implemented/BSOSEDepth.html index 50396f9b..e66d42ca 100644 --- a/docs/html/sections/Dataloaders/scalar/implemented/BSOSEDepth.html +++ b/docs/html/sections/Dataloaders/scalar/implemented/BSOSEDepth.html @@ -45,10 +45,10 @@ diff --git a/docs/html/sections/Dataloaders/scalar/implemented/BSOSESeaIce.html b/docs/html/sections/Dataloaders/scalar/implemented/BSOSESeaIce.html index c109775e..e5342369 100644 --- a/docs/html/sections/Dataloaders/scalar/implemented/BSOSESeaIce.html +++ b/docs/html/sections/Dataloaders/scalar/implemented/BSOSESeaIce.html @@ -45,10 +45,10 @@ diff --git a/docs/html/sections/Dataloaders/scalar/implemented/BalticSeaIce.html b/docs/html/sections/Dataloaders/scalar/implemented/BalticSeaIce.html index fbf1681b..87a46f6f 100644 --- a/docs/html/sections/Dataloaders/scalar/implemented/BalticSeaIce.html +++ b/docs/html/sections/Dataloaders/scalar/implemented/BalticSeaIce.html @@ -45,10 +45,10 @@ diff --git a/docs/html/sections/Dataloaders/scalar/implemented/BinaryGRF.html b/docs/html/sections/Dataloaders/scalar/implemented/BinaryGRF.html index 09b2d8f0..a57e64a2 100644 --- a/docs/html/sections/Dataloaders/scalar/implemented/BinaryGRF.html +++ b/docs/html/sections/Dataloaders/scalar/implemented/BinaryGRF.html @@ -21,7 +21,7 @@ - + @@ -45,10 +45,10 @@ @@ -151,7 +153,7 @@
    ", "
    " ], + col: [ 2, "", "
    " ], + tr: [ 2, "", "
    " ], + td: [ 3, "", "
    " ], + + _default: [ 0, "", "" ] +}; + +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + +// Support: IE <=9 only +if ( !support.option ) { + wrapMap.optgroup = wrapMap.option = [ 1, "" ]; +} + + +function getAll( context, tag ) { + + // Support: IE <=9 - 11 only + // Use typeof to avoid zero-argument method invocation on host objects (#15151) + var ret; + + if ( typeof context.getElementsByTagName !== "undefined" ) { + ret = context.getElementsByTagName( tag || "*" ); + + } else if ( typeof context.querySelectorAll !== "undefined" ) { + ret = context.querySelectorAll( tag || "*" ); + + } else { + ret = []; + } + + if ( tag === undefined || tag && nodeName( context, tag ) ) { + return jQuery.merge( [ context ], ret ); + } + + return ret; +} + + +// Mark scripts as having already been evaluated +function setGlobalEval( elems, refElements ) { + var i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + dataPriv.set( + elems[ i ], + "globalEval", + !refElements || dataPriv.get( refElements[ i ], "globalEval" ) + ); + } +} + + +var rhtml = /<|&#?\w+;/; + +function buildFragment( elems, context, scripts, selection, ignored ) { + var elem, tmp, tag, wrap, attached, j, + fragment = context.createDocumentFragment(), + nodes = [], + i = 0, + l = elems.length; + + for ( ; i < l; i++ ) { + elem = elems[ i ]; + + if ( elem || elem === 0 ) { + + // Add nodes directly + if ( toType( elem ) === "object" ) { + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); + + // Convert non-html into a text node + } else if ( !rhtml.test( elem ) ) { + nodes.push( context.createTextNode( elem ) ); + + // Convert html into DOM nodes + } else { + tmp = tmp || fragment.appendChild( context.createElement( "div" ) ); + + // Deserialize a standard representation + tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase(); + wrap = wrapMap[ tag ] || wrapMap._default; + tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ]; + + // Descend through wrappers to the right content + j = wrap[ 0 ]; + while ( j-- ) { + tmp = tmp.lastChild; + } + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( nodes, tmp.childNodes ); + + // Remember the top-level container + tmp = fragment.firstChild; + + // Ensure the created nodes are orphaned (#12392) + tmp.textContent = ""; + } + } + } + + // Remove wrapper from fragment + fragment.textContent = ""; + + i = 0; + while ( ( elem = nodes[ i++ ] ) ) { + + // Skip elements already in the context collection (trac-4087) + if ( selection && jQuery.inArray( elem, selection ) > -1 ) { + if ( ignored ) { + ignored.push( elem ); + } + continue; + } + + attached = isAttached( elem ); + + // Append to fragment + tmp = getAll( fragment.appendChild( elem ), "script" ); + + // Preserve script evaluation history + if ( attached ) { + setGlobalEval( tmp ); + } + + // Capture executables + if ( scripts ) { + j = 0; + while ( ( elem = tmp[ j++ ] ) ) { + if ( rscriptType.test( elem.type || "" ) ) { + scripts.push( elem ); + } + } + } + } + + return fragment; +} + + +var rtypenamespace = /^([^.]*)(?:\.(.+)|)/; + +function returnTrue() { + return true; +} + +function returnFalse() { + return false; +} + +// Support: IE <=9 - 11+ +// focus() and blur() are asynchronous, except when they are no-op. +// So expect focus to be synchronous when the element is already active, +// and blur to be synchronous when the element is not already active. +// (focus and blur are always synchronous in other supported browsers, +// this just defines when we can count on it). +function expectSync( elem, type ) { + return ( elem === safeActiveElement() ) === ( type === "focus" ); +} + +// Support: IE <=9 only +// Accessing document.activeElement can throw unexpectedly +// https://bugs.jquery.com/ticket/13393 +function safeActiveElement() { + try { + return document.activeElement; + } catch ( err ) { } +} + +function on( elem, types, selector, data, fn, one ) { + var origFn, type; + + // Types can be a map of types/handlers + if ( typeof types === "object" ) { + + // ( types-Object, selector, data ) + if ( typeof selector !== "string" ) { + + // ( types-Object, data ) + data = data || selector; + selector = undefined; + } + for ( type in types ) { + on( elem, type, selector, data, types[ type ], one ); + } + return elem; + } + + if ( data == null && fn == null ) { + + // ( types, fn ) + fn = selector; + data = selector = undefined; + } else if ( fn == null ) { + if ( typeof selector === "string" ) { + + // ( types, selector, fn ) + fn = data; + data = undefined; + } else { + + // ( types, data, fn ) + fn = data; + data = selector; + selector = undefined; + } + } + if ( fn === false ) { + fn = returnFalse; + } else if ( !fn ) { + return elem; + } + + if ( one === 1 ) { + origFn = fn; + fn = function( event ) { + + // Can use an empty set, since event contains the info + jQuery().off( event ); + return origFn.apply( this, arguments ); + }; + + // Use same guid so caller can remove using origFn + fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); + } + return elem.each( function() { + jQuery.event.add( this, types, fn, data, selector ); + } ); +} + +/* + * Helper functions for managing events -- not part of the public interface. + * Props to Dean Edwards' addEvent library for many of the ideas. + */ +jQuery.event = { + + global: {}, + + add: function( elem, types, handler, data, selector ) { + + var handleObjIn, eventHandle, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = dataPriv.get( elem ); + + // Only attach events to objects that accept data + if ( !acceptData( elem ) ) { + return; + } + + // Caller can pass in an object of custom data in lieu of the handler + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + selector = handleObjIn.selector; + } + + // Ensure that invalid selectors throw exceptions at attach time + // Evaluate against documentElement in case elem is a non-element node (e.g., document) + if ( selector ) { + jQuery.find.matchesSelector( documentElement, selector ); + } + + // Make sure that the handler has a unique ID, used to find/remove it later + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure and main handler, if this is the first + if ( !( events = elemData.events ) ) { + events = elemData.events = Object.create( null ); + } + if ( !( eventHandle = elemData.handle ) ) { + eventHandle = elemData.handle = function( e ) { + + // Discard the second event of a jQuery.event.trigger() and + // when an event is called after a page has unloaded + return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ? + jQuery.event.dispatch.apply( elem, arguments ) : undefined; + }; + } + + // Handle multiple events separated by a space + types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + + // There *must* be a type, no attaching namespace-only handlers + if ( !type ) { + continue; + } + + // If event changes its type, use the special event handlers for the changed type + special = jQuery.event.special[ type ] || {}; + + // If selector defined, determine special event api type, otherwise given type + type = ( selector ? special.delegateType : special.bindType ) || type; + + // Update special based on newly reset type + special = jQuery.event.special[ type ] || {}; + + // handleObj is passed to all event handlers + handleObj = jQuery.extend( { + type: type, + origType: origType, + data: data, + handler: handler, + guid: handler.guid, + selector: selector, + needsContext: selector && jQuery.expr.match.needsContext.test( selector ), + namespace: namespaces.join( "." ) + }, handleObjIn ); + + // Init the event handler queue if we're the first + if ( !( handlers = events[ type ] ) ) { + handlers = events[ type ] = []; + handlers.delegateCount = 0; + + // Only use addEventListener if the special events handler returns false + if ( !special.setup || + special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add to the element's handler list, delegates in front + if ( selector ) { + handlers.splice( handlers.delegateCount++, 0, handleObj ); + } else { + handlers.push( handleObj ); + } + + // Keep track of which events have ever been used, for event optimization + jQuery.event.global[ type ] = true; + } + + }, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, selector, mappedTypes ) { + + var j, origCount, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = dataPriv.hasData( elem ) && dataPriv.get( elem ); + + if ( !elemData || !( events = elemData.events ) ) { + return; + } + + // Once for each type.namespace in types; type may be omitted + types = ( types || "" ).match( rnothtmlwhite ) || [ "" ]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[ t ] ) || []; + type = origType = tmp[ 1 ]; + namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort(); + + // Unbind all events (on this namespace, if provided) for the element + if ( !type ) { + for ( type in events ) { + jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); + } + continue; + } + + special = jQuery.event.special[ type ] || {}; + type = ( selector ? special.delegateType : special.bindType ) || type; + handlers = events[ type ] || []; + tmp = tmp[ 2 ] && + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ); + + // Remove matching events + origCount = j = handlers.length; + while ( j-- ) { + handleObj = handlers[ j ]; + + if ( ( mappedTypes || origType === handleObj.origType ) && + ( !handler || handler.guid === handleObj.guid ) && + ( !tmp || tmp.test( handleObj.namespace ) ) && + ( !selector || selector === handleObj.selector || + selector === "**" && handleObj.selector ) ) { + handlers.splice( j, 1 ); + + if ( handleObj.selector ) { + handlers.delegateCount--; + } + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + } + + // Remove generic event handler if we removed something and no more handlers exist + // (avoids potential for endless recursion during removal of special event handlers) + if ( origCount && !handlers.length ) { + if ( !special.teardown || + special.teardown.call( elem, namespaces, elemData.handle ) === false ) { + + jQuery.removeEvent( elem, type, elemData.handle ); + } + + delete events[ type ]; + } + } + + // Remove data and the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + dataPriv.remove( elem, "handle events" ); + } + }, + + dispatch: function( nativeEvent ) { + + var i, j, ret, matched, handleObj, handlerQueue, + args = new Array( arguments.length ), + + // Make a writable jQuery.Event from the native event object + event = jQuery.event.fix( nativeEvent ), + + handlers = ( + dataPriv.get( this, "events" ) || Object.create( null ) + )[ event.type ] || [], + special = jQuery.event.special[ event.type ] || {}; + + // Use the fix-ed jQuery.Event rather than the (read-only) native event + args[ 0 ] = event; + + for ( i = 1; i < arguments.length; i++ ) { + args[ i ] = arguments[ i ]; + } + + event.delegateTarget = this; + + // Call the preDispatch hook for the mapped type, and let it bail if desired + if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { + return; + } + + // Determine handlers + handlerQueue = jQuery.event.handlers.call( this, event, handlers ); + + // Run delegates first; they may want to stop propagation beneath us + i = 0; + while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) { + event.currentTarget = matched.elem; + + j = 0; + while ( ( handleObj = matched.handlers[ j++ ] ) && + !event.isImmediatePropagationStopped() ) { + + // If the event is namespaced, then each handler is only invoked if it is + // specially universal or its namespaces are a superset of the event's. + if ( !event.rnamespace || handleObj.namespace === false || + event.rnamespace.test( handleObj.namespace ) ) { + + event.handleObj = handleObj; + event.data = handleObj.data; + + ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle || + handleObj.handler ).apply( matched.elem, args ); + + if ( ret !== undefined ) { + if ( ( event.result = ret ) === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + } + } + } + + // Call the postDispatch hook for the mapped type + if ( special.postDispatch ) { + special.postDispatch.call( this, event ); + } + + return event.result; + }, + + handlers: function( event, handlers ) { + var i, handleObj, sel, matchedHandlers, matchedSelectors, + handlerQueue = [], + delegateCount = handlers.delegateCount, + cur = event.target; + + // Find delegate handlers + if ( delegateCount && + + // Support: IE <=9 + // Black-hole SVG instance trees (trac-13180) + cur.nodeType && + + // Support: Firefox <=42 + // Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861) + // https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click + // Support: IE 11 only + // ...but not arrow key "clicks" of radio inputs, which can have `button` -1 (gh-2343) + !( event.type === "click" && event.button >= 1 ) ) { + + for ( ; cur !== this; cur = cur.parentNode || this ) { + + // Don't check non-elements (#13208) + // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) + if ( cur.nodeType === 1 && !( event.type === "click" && cur.disabled === true ) ) { + matchedHandlers = []; + matchedSelectors = {}; + for ( i = 0; i < delegateCount; i++ ) { + handleObj = handlers[ i ]; + + // Don't conflict with Object.prototype properties (#13203) + sel = handleObj.selector + " "; + + if ( matchedSelectors[ sel ] === undefined ) { + matchedSelectors[ sel ] = handleObj.needsContext ? + jQuery( sel, this ).index( cur ) > -1 : + jQuery.find( sel, this, null, [ cur ] ).length; + } + if ( matchedSelectors[ sel ] ) { + matchedHandlers.push( handleObj ); + } + } + if ( matchedHandlers.length ) { + handlerQueue.push( { elem: cur, handlers: matchedHandlers } ); + } + } + } + } + + // Add the remaining (directly-bound) handlers + cur = this; + if ( delegateCount < handlers.length ) { + handlerQueue.push( { elem: cur, handlers: handlers.slice( delegateCount ) } ); + } + + return handlerQueue; + }, + + addProp: function( name, hook ) { + Object.defineProperty( jQuery.Event.prototype, name, { + enumerable: true, + configurable: true, + + get: isFunction( hook ) ? + function() { + if ( this.originalEvent ) { + return hook( this.originalEvent ); + } + } : + function() { + if ( this.originalEvent ) { + return this.originalEvent[ name ]; + } + }, + + set: function( value ) { + Object.defineProperty( this, name, { + enumerable: true, + configurable: true, + writable: true, + value: value + } ); + } + } ); + }, + + fix: function( originalEvent ) { + return originalEvent[ jQuery.expando ] ? + originalEvent : + new jQuery.Event( originalEvent ); + }, + + special: { + load: { + + // Prevent triggered image.load events from bubbling to window.load + noBubble: true + }, + click: { + + // Utilize native event to ensure correct state for checkable inputs + setup: function( data ) { + + // For mutual compressibility with _default, replace `this` access with a local var. + // `|| data` is dead code meant only to preserve the variable through minification. + var el = this || data; + + // Claim the first handler + if ( rcheckableType.test( el.type ) && + el.click && nodeName( el, "input" ) ) { + + // dataPriv.set( el, "click", ... ) + leverageNative( el, "click", returnTrue ); + } + + // Return false to allow normal processing in the caller + return false; + }, + trigger: function( data ) { + + // For mutual compressibility with _default, replace `this` access with a local var. + // `|| data` is dead code meant only to preserve the variable through minification. + var el = this || data; + + // Force setup before triggering a click + if ( rcheckableType.test( el.type ) && + el.click && nodeName( el, "input" ) ) { + + leverageNative( el, "click" ); + } + + // Return non-false to allow normal event-path propagation + return true; + }, + + // For cross-browser consistency, suppress native .click() on links + // Also prevent it if we're currently inside a leveraged native-event stack + _default: function( event ) { + var target = event.target; + return rcheckableType.test( target.type ) && + target.click && nodeName( target, "input" ) && + dataPriv.get( target, "click" ) || + nodeName( target, "a" ); + } + }, + + beforeunload: { + postDispatch: function( event ) { + + // Support: Firefox 20+ + // Firefox doesn't alert if the returnValue field is not set. + if ( event.result !== undefined && event.originalEvent ) { + event.originalEvent.returnValue = event.result; + } + } + } + } +}; + +// Ensure the presence of an event listener that handles manually-triggered +// synthetic events by interrupting progress until reinvoked in response to +// *native* events that it fires directly, ensuring that state changes have +// already occurred before other listeners are invoked. +function leverageNative( el, type, expectSync ) { + + // Missing expectSync indicates a trigger call, which must force setup through jQuery.event.add + if ( !expectSync ) { + if ( dataPriv.get( el, type ) === undefined ) { + jQuery.event.add( el, type, returnTrue ); + } + return; + } + + // Register the controller as a special universal handler for all event namespaces + dataPriv.set( el, type, false ); + jQuery.event.add( el, type, { + namespace: false, + handler: function( event ) { + var notAsync, result, + saved = dataPriv.get( this, type ); + + if ( ( event.isTrigger & 1 ) && this[ type ] ) { + + // Interrupt processing of the outer synthetic .trigger()ed event + // Saved data should be false in such cases, but might be a leftover capture object + // from an async native handler (gh-4350) + if ( !saved.length ) { + + // Store arguments for use when handling the inner native event + // There will always be at least one argument (an event object), so this array + // will not be confused with a leftover capture object. + saved = slice.call( arguments ); + dataPriv.set( this, type, saved ); + + // Trigger the native event and capture its result + // Support: IE <=9 - 11+ + // focus() and blur() are asynchronous + notAsync = expectSync( this, type ); + this[ type ](); + result = dataPriv.get( this, type ); + if ( saved !== result || notAsync ) { + dataPriv.set( this, type, false ); + } else { + result = {}; + } + if ( saved !== result ) { + + // Cancel the outer synthetic event + event.stopImmediatePropagation(); + event.preventDefault(); + + // Support: Chrome 86+ + // In Chrome, if an element having a focusout handler is blurred by + // clicking outside of it, it invokes the handler synchronously. If + // that handler calls `.remove()` on the element, the data is cleared, + // leaving `result` undefined. We need to guard against this. + return result && result.value; + } + + // If this is an inner synthetic event for an event with a bubbling surrogate + // (focus or blur), assume that the surrogate already propagated from triggering the + // native event and prevent that from happening again here. + // This technically gets the ordering wrong w.r.t. to `.trigger()` (in which the + // bubbling surrogate propagates *after* the non-bubbling base), but that seems + // less bad than duplication. + } else if ( ( jQuery.event.special[ type ] || {} ).delegateType ) { + event.stopPropagation(); + } + + // If this is a native event triggered above, everything is now in order + // Fire an inner synthetic event with the original arguments + } else if ( saved.length ) { + + // ...and capture the result + dataPriv.set( this, type, { + value: jQuery.event.trigger( + + // Support: IE <=9 - 11+ + // Extend with the prototype to reset the above stopImmediatePropagation() + jQuery.extend( saved[ 0 ], jQuery.Event.prototype ), + saved.slice( 1 ), + this + ) + } ); + + // Abort handling of the native event + event.stopImmediatePropagation(); + } + } + } ); +} + +jQuery.removeEvent = function( elem, type, handle ) { + + // This "if" is needed for plain objects + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle ); + } +}; + +jQuery.Event = function( src, props ) { + + // Allow instantiation without the 'new' keyword + if ( !( this instanceof jQuery.Event ) ) { + return new jQuery.Event( src, props ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = src.defaultPrevented || + src.defaultPrevented === undefined && + + // Support: Android <=2.3 only + src.returnValue === false ? + returnTrue : + returnFalse; + + // Create target properties + // Support: Safari <=6 - 7 only + // Target should not be a text node (#504, #13143) + this.target = ( src.target && src.target.nodeType === 3 ) ? + src.target.parentNode : + src.target; + + this.currentTarget = src.currentTarget; + this.relatedTarget = src.relatedTarget; + + // Event type + } else { + this.type = src; + } + + // Put explicitly provided properties onto the event object + if ( props ) { + jQuery.extend( this, props ); + } + + // Create a timestamp if incoming event doesn't have one + this.timeStamp = src && src.timeStamp || Date.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + constructor: jQuery.Event, + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse, + isSimulated: false, + + preventDefault: function() { + var e = this.originalEvent; + + this.isDefaultPrevented = returnTrue; + + if ( e && !this.isSimulated ) { + e.preventDefault(); + } + }, + stopPropagation: function() { + var e = this.originalEvent; + + this.isPropagationStopped = returnTrue; + + if ( e && !this.isSimulated ) { + e.stopPropagation(); + } + }, + stopImmediatePropagation: function() { + var e = this.originalEvent; + + this.isImmediatePropagationStopped = returnTrue; + + if ( e && !this.isSimulated ) { + e.stopImmediatePropagation(); + } + + this.stopPropagation(); + } +}; + +// Includes all common event props including KeyEvent and MouseEvent specific props +jQuery.each( { + altKey: true, + bubbles: true, + cancelable: true, + changedTouches: true, + ctrlKey: true, + detail: true, + eventPhase: true, + metaKey: true, + pageX: true, + pageY: true, + shiftKey: true, + view: true, + "char": true, + code: true, + charCode: true, + key: true, + keyCode: true, + button: true, + buttons: true, + clientX: true, + clientY: true, + offsetX: true, + offsetY: true, + pointerId: true, + pointerType: true, + screenX: true, + screenY: true, + targetTouches: true, + toElement: true, + touches: true, + which: true +}, jQuery.event.addProp ); + +jQuery.each( { focus: "focusin", blur: "focusout" }, function( type, delegateType ) { + jQuery.event.special[ type ] = { + + // Utilize native event if possible so blur/focus sequence is correct + setup: function() { + + // Claim the first handler + // dataPriv.set( this, "focus", ... ) + // dataPriv.set( this, "blur", ... ) + leverageNative( this, type, expectSync ); + + // Return false to allow normal processing in the caller + return false; + }, + trigger: function() { + + // Force setup before trigger + leverageNative( this, type ); + + // Return non-false to allow normal event-path propagation + return true; + }, + + // Suppress native focus or blur as it's already being fired + // in leverageNative. + _default: function() { + return true; + }, + + delegateType: delegateType + }; +} ); + +// Create mouseenter/leave events using mouseover/out and event-time checks +// so that event delegation works in jQuery. +// Do the same for pointerenter/pointerleave and pointerover/pointerout +// +// Support: Safari 7 only +// Safari sends mouseenter too often; see: +// https://bugs.chromium.org/p/chromium/issues/detail?id=470258 +// for the description of the bug (it existed in older Chrome versions as well). +jQuery.each( { + mouseenter: "mouseover", + mouseleave: "mouseout", + pointerenter: "pointerover", + pointerleave: "pointerout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + delegateType: fix, + bindType: fix, + + handle: function( event ) { + var ret, + target = this, + related = event.relatedTarget, + handleObj = event.handleObj; + + // For mouseenter/leave call the handler if related is outside the target. + // NB: No relatedTarget if the mouse left/entered the browser window + if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) { + event.type = handleObj.origType; + ret = handleObj.handler.apply( this, arguments ); + event.type = fix; + } + return ret; + } + }; +} ); + +jQuery.fn.extend( { + + on: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn ); + }, + one: function( types, selector, data, fn ) { + return on( this, types, selector, data, fn, 1 ); + }, + off: function( types, selector, fn ) { + var handleObj, type; + if ( types && types.preventDefault && types.handleObj ) { + + // ( event ) dispatched jQuery.Event + handleObj = types.handleObj; + jQuery( types.delegateTarget ).off( + handleObj.namespace ? + handleObj.origType + "." + handleObj.namespace : + handleObj.origType, + handleObj.selector, + handleObj.handler + ); + return this; + } + if ( typeof types === "object" ) { + + // ( types-object [, selector] ) + for ( type in types ) { + this.off( type, selector, types[ type ] ); + } + return this; + } + if ( selector === false || typeof selector === "function" ) { + + // ( types [, fn] ) + fn = selector; + selector = undefined; + } + if ( fn === false ) { + fn = returnFalse; + } + return this.each( function() { + jQuery.event.remove( this, types, fn, selector ); + } ); + } +} ); + + +var + + // Support: IE <=10 - 11, Edge 12 - 13 only + // In IE/Edge using regex groups here causes severe slowdowns. + // See https://connect.microsoft.com/IE/feedback/details/1736512/ + rnoInnerhtml = /\s*$/g; + +// Prefer a tbody over its parent table for containing new rows +function manipulationTarget( elem, content ) { + if ( nodeName( elem, "table" ) && + nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ) { + + return jQuery( elem ).children( "tbody" )[ 0 ] || elem; + } + + return elem; +} + +// Replace/restore the type attribute of script elements for safe DOM manipulation +function disableScript( elem ) { + elem.type = ( elem.getAttribute( "type" ) !== null ) + "/" + elem.type; + return elem; +} +function restoreScript( elem ) { + if ( ( elem.type || "" ).slice( 0, 5 ) === "true/" ) { + elem.type = elem.type.slice( 5 ); + } else { + elem.removeAttribute( "type" ); + } + + return elem; +} + +function cloneCopyEvent( src, dest ) { + var i, l, type, pdataOld, udataOld, udataCur, events; + + if ( dest.nodeType !== 1 ) { + return; + } + + // 1. Copy private data: events, handlers, etc. + if ( dataPriv.hasData( src ) ) { + pdataOld = dataPriv.get( src ); + events = pdataOld.events; + + if ( events ) { + dataPriv.remove( dest, "handle events" ); + + for ( type in events ) { + for ( i = 0, l = events[ type ].length; i < l; i++ ) { + jQuery.event.add( dest, type, events[ type ][ i ] ); + } + } + } + } + + // 2. Copy user data + if ( dataUser.hasData( src ) ) { + udataOld = dataUser.access( src ); + udataCur = jQuery.extend( {}, udataOld ); + + dataUser.set( dest, udataCur ); + } +} + +// Fix IE bugs, see support tests +function fixInput( src, dest ) { + var nodeName = dest.nodeName.toLowerCase(); + + // Fails to persist the checked state of a cloned checkbox or radio button. + if ( nodeName === "input" && rcheckableType.test( src.type ) ) { + dest.checked = src.checked; + + // Fails to return the selected option to the default selected state when cloning options + } else if ( nodeName === "input" || nodeName === "textarea" ) { + dest.defaultValue = src.defaultValue; + } +} + +function domManip( collection, args, callback, ignored ) { + + // Flatten any nested arrays + args = flat( args ); + + var fragment, first, scripts, hasScripts, node, doc, + i = 0, + l = collection.length, + iNoClone = l - 1, + value = args[ 0 ], + valueIsFunction = isFunction( value ); + + // We can't cloneNode fragments that contain checked, in WebKit + if ( valueIsFunction || + ( l > 1 && typeof value === "string" && + !support.checkClone && rchecked.test( value ) ) ) { + return collection.each( function( index ) { + var self = collection.eq( index ); + if ( valueIsFunction ) { + args[ 0 ] = value.call( this, index, self.html() ); + } + domManip( self, args, callback, ignored ); + } ); + } + + if ( l ) { + fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored ); + first = fragment.firstChild; + + if ( fragment.childNodes.length === 1 ) { + fragment = first; + } + + // Require either new content or an interest in ignored elements to invoke the callback + if ( first || ignored ) { + scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); + hasScripts = scripts.length; + + // Use the original fragment for the last item + // instead of the first because it can end up + // being emptied incorrectly in certain situations (#8070). + for ( ; i < l; i++ ) { + node = fragment; + + if ( i !== iNoClone ) { + node = jQuery.clone( node, true, true ); + + // Keep references to cloned scripts for later restoration + if ( hasScripts ) { + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + jQuery.merge( scripts, getAll( node, "script" ) ); + } + } + + callback.call( collection[ i ], node, i ); + } + + if ( hasScripts ) { + doc = scripts[ scripts.length - 1 ].ownerDocument; + + // Reenable scripts + jQuery.map( scripts, restoreScript ); + + // Evaluate executable scripts on first document insertion + for ( i = 0; i < hasScripts; i++ ) { + node = scripts[ i ]; + if ( rscriptType.test( node.type || "" ) && + !dataPriv.access( node, "globalEval" ) && + jQuery.contains( doc, node ) ) { + + if ( node.src && ( node.type || "" ).toLowerCase() !== "module" ) { + + // Optional AJAX dependency, but won't run scripts if not present + if ( jQuery._evalUrl && !node.noModule ) { + jQuery._evalUrl( node.src, { + nonce: node.nonce || node.getAttribute( "nonce" ) + }, doc ); + } + } else { + DOMEval( node.textContent.replace( rcleanScript, "" ), node, doc ); + } + } + } + } + } + } + + return collection; +} + +function remove( elem, selector, keepData ) { + var node, + nodes = selector ? jQuery.filter( selector, elem ) : elem, + i = 0; + + for ( ; ( node = nodes[ i ] ) != null; i++ ) { + if ( !keepData && node.nodeType === 1 ) { + jQuery.cleanData( getAll( node ) ); + } + + if ( node.parentNode ) { + if ( keepData && isAttached( node ) ) { + setGlobalEval( getAll( node, "script" ) ); + } + node.parentNode.removeChild( node ); + } + } + + return elem; +} + +jQuery.extend( { + htmlPrefilter: function( html ) { + return html; + }, + + clone: function( elem, dataAndEvents, deepDataAndEvents ) { + var i, l, srcElements, destElements, + clone = elem.cloneNode( true ), + inPage = isAttached( elem ); + + // Fix IE cloning issues + if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) && + !jQuery.isXMLDoc( elem ) ) { + + // We eschew Sizzle here for performance reasons: https://jsperf.com/getall-vs-sizzle/2 + destElements = getAll( clone ); + srcElements = getAll( elem ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + fixInput( srcElements[ i ], destElements[ i ] ); + } + } + + // Copy the events from the original to the clone + if ( dataAndEvents ) { + if ( deepDataAndEvents ) { + srcElements = srcElements || getAll( elem ); + destElements = destElements || getAll( clone ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + cloneCopyEvent( srcElements[ i ], destElements[ i ] ); + } + } else { + cloneCopyEvent( elem, clone ); + } + } + + // Preserve script evaluation history + destElements = getAll( clone, "script" ); + if ( destElements.length > 0 ) { + setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); + } + + // Return the cloned set + return clone; + }, + + cleanData: function( elems ) { + var data, elem, type, + special = jQuery.event.special, + i = 0; + + for ( ; ( elem = elems[ i ] ) !== undefined; i++ ) { + if ( acceptData( elem ) ) { + if ( ( data = elem[ dataPriv.expando ] ) ) { + if ( data.events ) { + for ( type in data.events ) { + if ( special[ type ] ) { + jQuery.event.remove( elem, type ); + + // This is a shortcut to avoid jQuery.event.remove's overhead + } else { + jQuery.removeEvent( elem, type, data.handle ); + } + } + } + + // Support: Chrome <=35 - 45+ + // Assign undefined instead of using delete, see Data#remove + elem[ dataPriv.expando ] = undefined; + } + if ( elem[ dataUser.expando ] ) { + + // Support: Chrome <=35 - 45+ + // Assign undefined instead of using delete, see Data#remove + elem[ dataUser.expando ] = undefined; + } + } + } + } +} ); + +jQuery.fn.extend( { + detach: function( selector ) { + return remove( this, selector, true ); + }, + + remove: function( selector ) { + return remove( this, selector ); + }, + + text: function( value ) { + return access( this, function( value ) { + return value === undefined ? + jQuery.text( this ) : + this.empty().each( function() { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + this.textContent = value; + } + } ); + }, null, value, arguments.length ); + }, + + append: function() { + return domManip( this, arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.appendChild( elem ); + } + } ); + }, + + prepend: function() { + return domManip( this, arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.insertBefore( elem, target.firstChild ); + } + } ); + }, + + before: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this ); + } + } ); + }, + + after: function() { + return domManip( this, arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this.nextSibling ); + } + } ); + }, + + empty: function() { + var elem, + i = 0; + + for ( ; ( elem = this[ i ] ) != null; i++ ) { + if ( elem.nodeType === 1 ) { + + // Prevent memory leaks + jQuery.cleanData( getAll( elem, false ) ); + + // Remove any remaining nodes + elem.textContent = ""; + } + } + + return this; + }, + + clone: function( dataAndEvents, deepDataAndEvents ) { + dataAndEvents = dataAndEvents == null ? false : dataAndEvents; + deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; + + return this.map( function() { + return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); + } ); + }, + + html: function( value ) { + return access( this, function( value ) { + var elem = this[ 0 ] || {}, + i = 0, + l = this.length; + + if ( value === undefined && elem.nodeType === 1 ) { + return elem.innerHTML; + } + + // See if we can take a shortcut and just use innerHTML + if ( typeof value === "string" && !rnoInnerhtml.test( value ) && + !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) { + + value = jQuery.htmlPrefilter( value ); + + try { + for ( ; i < l; i++ ) { + elem = this[ i ] || {}; + + // Remove element nodes and prevent memory leaks + if ( elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem, false ) ); + elem.innerHTML = value; + } + } + + elem = 0; + + // If using innerHTML throws an exception, use the fallback method + } catch ( e ) {} + } + + if ( elem ) { + this.empty().append( value ); + } + }, null, value, arguments.length ); + }, + + replaceWith: function() { + var ignored = []; + + // Make the changes, replacing each non-ignored context element with the new content + return domManip( this, arguments, function( elem ) { + var parent = this.parentNode; + + if ( jQuery.inArray( this, ignored ) < 0 ) { + jQuery.cleanData( getAll( this ) ); + if ( parent ) { + parent.replaceChild( elem, this ); + } + } + + // Force callback invocation + }, ignored ); + } +} ); + +jQuery.each( { + appendTo: "append", + prependTo: "prepend", + insertBefore: "before", + insertAfter: "after", + replaceAll: "replaceWith" +}, function( name, original ) { + jQuery.fn[ name ] = function( selector ) { + var elems, + ret = [], + insert = jQuery( selector ), + last = insert.length - 1, + i = 0; + + for ( ; i <= last; i++ ) { + elems = i === last ? this : this.clone( true ); + jQuery( insert[ i ] )[ original ]( elems ); + + // Support: Android <=4.0 only, PhantomJS 1 only + // .get() because push.apply(_, arraylike) throws on ancient WebKit + push.apply( ret, elems.get() ); + } + + return this.pushStack( ret ); + }; +} ); +var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" ); + +var getStyles = function( elem ) { + + // Support: IE <=11 only, Firefox <=30 (#15098, #14150) + // IE throws on elements created in popups + // FF meanwhile throws on frame elements through "defaultView.getComputedStyle" + var view = elem.ownerDocument.defaultView; + + if ( !view || !view.opener ) { + view = window; + } + + return view.getComputedStyle( elem ); + }; + +var swap = function( elem, options, callback ) { + var ret, name, + old = {}; + + // Remember the old values, and insert the new ones + for ( name in options ) { + old[ name ] = elem.style[ name ]; + elem.style[ name ] = options[ name ]; + } + + ret = callback.call( elem ); + + // Revert the old values + for ( name in options ) { + elem.style[ name ] = old[ name ]; + } + + return ret; +}; + + +var rboxStyle = new RegExp( cssExpand.join( "|" ), "i" ); + + + +( function() { + + // Executing both pixelPosition & boxSizingReliable tests require only one layout + // so they're executed at the same time to save the second computation. + function computeStyleTests() { + + // This is a singleton, we need to execute it only once + if ( !div ) { + return; + } + + container.style.cssText = "position:absolute;left:-11111px;width:60px;" + + "margin-top:1px;padding:0;border:0"; + div.style.cssText = + "position:relative;display:block;box-sizing:border-box;overflow:scroll;" + + "margin:auto;border:1px;padding:1px;" + + "width:60%;top:1%"; + documentElement.appendChild( container ).appendChild( div ); + + var divStyle = window.getComputedStyle( div ); + pixelPositionVal = divStyle.top !== "1%"; + + // Support: Android 4.0 - 4.3 only, Firefox <=3 - 44 + reliableMarginLeftVal = roundPixelMeasures( divStyle.marginLeft ) === 12; + + // Support: Android 4.0 - 4.3 only, Safari <=9.1 - 10.1, iOS <=7.0 - 9.3 + // Some styles come back with percentage values, even though they shouldn't + div.style.right = "60%"; + pixelBoxStylesVal = roundPixelMeasures( divStyle.right ) === 36; + + // Support: IE 9 - 11 only + // Detect misreporting of content dimensions for box-sizing:border-box elements + boxSizingReliableVal = roundPixelMeasures( divStyle.width ) === 36; + + // Support: IE 9 only + // Detect overflow:scroll screwiness (gh-3699) + // Support: Chrome <=64 + // Don't get tricked when zoom affects offsetWidth (gh-4029) + div.style.position = "absolute"; + scrollboxSizeVal = roundPixelMeasures( div.offsetWidth / 3 ) === 12; + + documentElement.removeChild( container ); + + // Nullify the div so it wouldn't be stored in the memory and + // it will also be a sign that checks already performed + div = null; + } + + function roundPixelMeasures( measure ) { + return Math.round( parseFloat( measure ) ); + } + + var pixelPositionVal, boxSizingReliableVal, scrollboxSizeVal, pixelBoxStylesVal, + reliableTrDimensionsVal, reliableMarginLeftVal, + container = document.createElement( "div" ), + div = document.createElement( "div" ); + + // Finish early in limited (non-browser) environments + if ( !div.style ) { + return; + } + + // Support: IE <=9 - 11 only + // Style of cloned element affects source element cloned (#8908) + div.style.backgroundClip = "content-box"; + div.cloneNode( true ).style.backgroundClip = ""; + support.clearCloneStyle = div.style.backgroundClip === "content-box"; + + jQuery.extend( support, { + boxSizingReliable: function() { + computeStyleTests(); + return boxSizingReliableVal; + }, + pixelBoxStyles: function() { + computeStyleTests(); + return pixelBoxStylesVal; + }, + pixelPosition: function() { + computeStyleTests(); + return pixelPositionVal; + }, + reliableMarginLeft: function() { + computeStyleTests(); + return reliableMarginLeftVal; + }, + scrollboxSize: function() { + computeStyleTests(); + return scrollboxSizeVal; + }, + + // Support: IE 9 - 11+, Edge 15 - 18+ + // IE/Edge misreport `getComputedStyle` of table rows with width/height + // set in CSS while `offset*` properties report correct values. + // Behavior in IE 9 is more subtle than in newer versions & it passes + // some versions of this test; make sure not to make it pass there! + // + // Support: Firefox 70+ + // Only Firefox includes border widths + // in computed dimensions. (gh-4529) + reliableTrDimensions: function() { + var table, tr, trChild, trStyle; + if ( reliableTrDimensionsVal == null ) { + table = document.createElement( "table" ); + tr = document.createElement( "tr" ); + trChild = document.createElement( "div" ); + + table.style.cssText = "position:absolute;left:-11111px;border-collapse:separate"; + tr.style.cssText = "border:1px solid"; + + // Support: Chrome 86+ + // Height set through cssText does not get applied. + // Computed height then comes back as 0. + tr.style.height = "1px"; + trChild.style.height = "9px"; + + // Support: Android 8 Chrome 86+ + // In our bodyBackground.html iframe, + // display for all div elements is set to "inline", + // which causes a problem only in Android 8 Chrome 86. + // Ensuring the div is display: block + // gets around this issue. + trChild.style.display = "block"; + + documentElement + .appendChild( table ) + .appendChild( tr ) + .appendChild( trChild ); + + trStyle = window.getComputedStyle( tr ); + reliableTrDimensionsVal = ( parseInt( trStyle.height, 10 ) + + parseInt( trStyle.borderTopWidth, 10 ) + + parseInt( trStyle.borderBottomWidth, 10 ) ) === tr.offsetHeight; + + documentElement.removeChild( table ); + } + return reliableTrDimensionsVal; + } + } ); +} )(); + + +function curCSS( elem, name, computed ) { + var width, minWidth, maxWidth, ret, + + // Support: Firefox 51+ + // Retrieving style before computed somehow + // fixes an issue with getting wrong values + // on detached elements + style = elem.style; + + computed = computed || getStyles( elem ); + + // getPropertyValue is needed for: + // .css('filter') (IE 9 only, #12537) + // .css('--customProperty) (#3144) + if ( computed ) { + ret = computed.getPropertyValue( name ) || computed[ name ]; + + if ( ret === "" && !isAttached( elem ) ) { + ret = jQuery.style( elem, name ); + } + + // A tribute to the "awesome hack by Dean Edwards" + // Android Browser returns percentage for some values, + // but width seems to be reliably pixels. + // This is against the CSSOM draft spec: + // https://drafts.csswg.org/cssom/#resolved-values + if ( !support.pixelBoxStyles() && rnumnonpx.test( ret ) && rboxStyle.test( name ) ) { + + // Remember the original values + width = style.width; + minWidth = style.minWidth; + maxWidth = style.maxWidth; + + // Put in the new values to get a computed value out + style.minWidth = style.maxWidth = style.width = ret; + ret = computed.width; + + // Revert the changed values + style.width = width; + style.minWidth = minWidth; + style.maxWidth = maxWidth; + } + } + + return ret !== undefined ? + + // Support: IE <=9 - 11 only + // IE returns zIndex value as an integer. + ret + "" : + ret; +} + + +function addGetHookIf( conditionFn, hookFn ) { + + // Define the hook, we'll check on the first run if it's really needed. + return { + get: function() { + if ( conditionFn() ) { + + // Hook not needed (or it's not possible to use it due + // to missing dependency), remove it. + delete this.get; + return; + } + + // Hook needed; redefine it so that the support test is not executed again. + return ( this.get = hookFn ).apply( this, arguments ); + } + }; +} + + +var cssPrefixes = [ "Webkit", "Moz", "ms" ], + emptyStyle = document.createElement( "div" ).style, + vendorProps = {}; + +// Return a vendor-prefixed property or undefined +function vendorPropName( name ) { + + // Check for vendor prefixed names + var capName = name[ 0 ].toUpperCase() + name.slice( 1 ), + i = cssPrefixes.length; + + while ( i-- ) { + name = cssPrefixes[ i ] + capName; + if ( name in emptyStyle ) { + return name; + } + } +} + +// Return a potentially-mapped jQuery.cssProps or vendor prefixed property +function finalPropName( name ) { + var final = jQuery.cssProps[ name ] || vendorProps[ name ]; + + if ( final ) { + return final; + } + if ( name in emptyStyle ) { + return name; + } + return vendorProps[ name ] = vendorPropName( name ) || name; +} + + +var + + // Swappable if display is none or starts with table + // except "table", "table-cell", or "table-caption" + // See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display + rdisplayswap = /^(none|table(?!-c[ea]).+)/, + rcustomProp = /^--/, + cssShow = { position: "absolute", visibility: "hidden", display: "block" }, + cssNormalTransform = { + letterSpacing: "0", + fontWeight: "400" + }; + +function setPositiveNumber( _elem, value, subtract ) { + + // Any relative (+/-) values have already been + // normalized at this point + var matches = rcssNum.exec( value ); + return matches ? + + // Guard against undefined "subtract", e.g., when used as in cssHooks + Math.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || "px" ) : + value; +} + +function boxModelAdjustment( elem, dimension, box, isBorderBox, styles, computedVal ) { + var i = dimension === "width" ? 1 : 0, + extra = 0, + delta = 0; + + // Adjustment may not be necessary + if ( box === ( isBorderBox ? "border" : "content" ) ) { + return 0; + } + + for ( ; i < 4; i += 2 ) { + + // Both box models exclude margin + if ( box === "margin" ) { + delta += jQuery.css( elem, box + cssExpand[ i ], true, styles ); + } + + // If we get here with a content-box, we're seeking "padding" or "border" or "margin" + if ( !isBorderBox ) { + + // Add padding + delta += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + + // For "border" or "margin", add border + if ( box !== "padding" ) { + delta += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + + // But still keep track of it otherwise + } else { + extra += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + + // If we get here with a border-box (content + padding + border), we're seeking "content" or + // "padding" or "margin" + } else { + + // For "content", subtract padding + if ( box === "content" ) { + delta -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + } + + // For "content" or "padding", subtract border + if ( box !== "margin" ) { + delta -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + } + } + + // Account for positive content-box scroll gutter when requested by providing computedVal + if ( !isBorderBox && computedVal >= 0 ) { + + // offsetWidth/offsetHeight is a rounded sum of content, padding, scroll gutter, and border + // Assuming integer scroll gutter, subtract the rest and round down + delta += Math.max( 0, Math.ceil( + elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - + computedVal - + delta - + extra - + 0.5 + + // If offsetWidth/offsetHeight is unknown, then we can't determine content-box scroll gutter + // Use an explicit zero to avoid NaN (gh-3964) + ) ) || 0; + } + + return delta; +} + +function getWidthOrHeight( elem, dimension, extra ) { + + // Start with computed style + var styles = getStyles( elem ), + + // To avoid forcing a reflow, only fetch boxSizing if we need it (gh-4322). + // Fake content-box until we know it's needed to know the true value. + boxSizingNeeded = !support.boxSizingReliable() || extra, + isBorderBox = boxSizingNeeded && + jQuery.css( elem, "boxSizing", false, styles ) === "border-box", + valueIsBorderBox = isBorderBox, + + val = curCSS( elem, dimension, styles ), + offsetProp = "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ); + + // Support: Firefox <=54 + // Return a confounding non-pixel value or feign ignorance, as appropriate. + if ( rnumnonpx.test( val ) ) { + if ( !extra ) { + return val; + } + val = "auto"; + } + + + // Support: IE 9 - 11 only + // Use offsetWidth/offsetHeight for when box sizing is unreliable. + // In those cases, the computed value can be trusted to be border-box. + if ( ( !support.boxSizingReliable() && isBorderBox || + + // Support: IE 10 - 11+, Edge 15 - 18+ + // IE/Edge misreport `getComputedStyle` of table rows with width/height + // set in CSS while `offset*` properties report correct values. + // Interestingly, in some cases IE 9 doesn't suffer from this issue. + !support.reliableTrDimensions() && nodeName( elem, "tr" ) || + + // Fall back to offsetWidth/offsetHeight when value is "auto" + // This happens for inline elements with no explicit setting (gh-3571) + val === "auto" || + + // Support: Android <=4.1 - 4.3 only + // Also use offsetWidth/offsetHeight for misreported inline dimensions (gh-3602) + !parseFloat( val ) && jQuery.css( elem, "display", false, styles ) === "inline" ) && + + // Make sure the element is visible & connected + elem.getClientRects().length ) { + + isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box"; + + // Where available, offsetWidth/offsetHeight approximate border box dimensions. + // Where not available (e.g., SVG), assume unreliable box-sizing and interpret the + // retrieved value as a content box dimension. + valueIsBorderBox = offsetProp in elem; + if ( valueIsBorderBox ) { + val = elem[ offsetProp ]; + } + } + + // Normalize "" and auto + val = parseFloat( val ) || 0; + + // Adjust for the element's box model + return ( val + + boxModelAdjustment( + elem, + dimension, + extra || ( isBorderBox ? "border" : "content" ), + valueIsBorderBox, + styles, + + // Provide the current computed size to request scroll gutter calculation (gh-3589) + val + ) + ) + "px"; +} + +jQuery.extend( { + + // Add in style property hooks for overriding the default + // behavior of getting and setting a style property + cssHooks: { + opacity: { + get: function( elem, computed ) { + if ( computed ) { + + // We should always get a number back from opacity + var ret = curCSS( elem, "opacity" ); + return ret === "" ? "1" : ret; + } + } + } + }, + + // Don't automatically add "px" to these possibly-unitless properties + cssNumber: { + "animationIterationCount": true, + "columnCount": true, + "fillOpacity": true, + "flexGrow": true, + "flexShrink": true, + "fontWeight": true, + "gridArea": true, + "gridColumn": true, + "gridColumnEnd": true, + "gridColumnStart": true, + "gridRow": true, + "gridRowEnd": true, + "gridRowStart": true, + "lineHeight": true, + "opacity": true, + "order": true, + "orphans": true, + "widows": true, + "zIndex": true, + "zoom": true + }, + + // Add in properties whose names you wish to fix before + // setting or getting the value + cssProps: {}, + + // Get and set the style property on a DOM Node + style: function( elem, name, value, extra ) { + + // Don't set styles on text and comment nodes + if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { + return; + } + + // Make sure that we're working with the right name + var ret, type, hooks, + origName = camelCase( name ), + isCustomProp = rcustomProp.test( name ), + style = elem.style; + + // Make sure that we're working with the right name. We don't + // want to query the value if it is a CSS custom property + // since they are user-defined. + if ( !isCustomProp ) { + name = finalPropName( origName ); + } + + // Gets hook for the prefixed version, then unprefixed version + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // Check if we're setting a value + if ( value !== undefined ) { + type = typeof value; + + // Convert "+=" or "-=" to relative numbers (#7345) + if ( type === "string" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) { + value = adjustCSS( elem, name, ret ); + + // Fixes bug #9237 + type = "number"; + } + + // Make sure that null and NaN values aren't set (#7116) + if ( value == null || value !== value ) { + return; + } + + // If a number was passed in, add the unit (except for certain CSS properties) + // The isCustomProp check can be removed in jQuery 4.0 when we only auto-append + // "px" to a few hardcoded values. + if ( type === "number" && !isCustomProp ) { + value += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? "" : "px" ); + } + + // background-* props affect original clone's values + if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) { + style[ name ] = "inherit"; + } + + // If a hook was provided, use that value, otherwise just set the specified value + if ( !hooks || !( "set" in hooks ) || + ( value = hooks.set( elem, value, extra ) ) !== undefined ) { + + if ( isCustomProp ) { + style.setProperty( name, value ); + } else { + style[ name ] = value; + } + } + + } else { + + // If a hook was provided get the non-computed value from there + if ( hooks && "get" in hooks && + ( ret = hooks.get( elem, false, extra ) ) !== undefined ) { + + return ret; + } + + // Otherwise just get the value from the style object + return style[ name ]; + } + }, + + css: function( elem, name, extra, styles ) { + var val, num, hooks, + origName = camelCase( name ), + isCustomProp = rcustomProp.test( name ); + + // Make sure that we're working with the right name. We don't + // want to modify the value if it is a CSS custom property + // since they are user-defined. + if ( !isCustomProp ) { + name = finalPropName( origName ); + } + + // Try prefixed name followed by the unprefixed name + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // If a hook was provided get the computed value from there + if ( hooks && "get" in hooks ) { + val = hooks.get( elem, true, extra ); + } + + // Otherwise, if a way to get the computed value exists, use that + if ( val === undefined ) { + val = curCSS( elem, name, styles ); + } + + // Convert "normal" to computed value + if ( val === "normal" && name in cssNormalTransform ) { + val = cssNormalTransform[ name ]; + } + + // Make numeric if forced or a qualifier was provided and val looks numeric + if ( extra === "" || extra ) { + num = parseFloat( val ); + return extra === true || isFinite( num ) ? num || 0 : val; + } + + return val; + } +} ); + +jQuery.each( [ "height", "width" ], function( _i, dimension ) { + jQuery.cssHooks[ dimension ] = { + get: function( elem, computed, extra ) { + if ( computed ) { + + // Certain elements can have dimension info if we invisibly show them + // but it must have a current display style that would benefit + return rdisplayswap.test( jQuery.css( elem, "display" ) ) && + + // Support: Safari 8+ + // Table columns in Safari have non-zero offsetWidth & zero + // getBoundingClientRect().width unless display is changed. + // Support: IE <=11 only + // Running getBoundingClientRect on a disconnected node + // in IE throws an error. + ( !elem.getClientRects().length || !elem.getBoundingClientRect().width ) ? + swap( elem, cssShow, function() { + return getWidthOrHeight( elem, dimension, extra ); + } ) : + getWidthOrHeight( elem, dimension, extra ); + } + }, + + set: function( elem, value, extra ) { + var matches, + styles = getStyles( elem ), + + // Only read styles.position if the test has a chance to fail + // to avoid forcing a reflow. + scrollboxSizeBuggy = !support.scrollboxSize() && + styles.position === "absolute", + + // To avoid forcing a reflow, only fetch boxSizing if we need it (gh-3991) + boxSizingNeeded = scrollboxSizeBuggy || extra, + isBorderBox = boxSizingNeeded && + jQuery.css( elem, "boxSizing", false, styles ) === "border-box", + subtract = extra ? + boxModelAdjustment( + elem, + dimension, + extra, + isBorderBox, + styles + ) : + 0; + + // Account for unreliable border-box dimensions by comparing offset* to computed and + // faking a content-box to get border and padding (gh-3699) + if ( isBorderBox && scrollboxSizeBuggy ) { + subtract -= Math.ceil( + elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - + parseFloat( styles[ dimension ] ) - + boxModelAdjustment( elem, dimension, "border", false, styles ) - + 0.5 + ); + } + + // Convert to pixels if value adjustment is needed + if ( subtract && ( matches = rcssNum.exec( value ) ) && + ( matches[ 3 ] || "px" ) !== "px" ) { + + elem.style[ dimension ] = value; + value = jQuery.css( elem, dimension ); + } + + return setPositiveNumber( elem, value, subtract ); + } + }; +} ); + +jQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft, + function( elem, computed ) { + if ( computed ) { + return ( parseFloat( curCSS( elem, "marginLeft" ) ) || + elem.getBoundingClientRect().left - + swap( elem, { marginLeft: 0 }, function() { + return elem.getBoundingClientRect().left; + } ) + ) + "px"; + } + } +); + +// These hooks are used by animate to expand properties +jQuery.each( { + margin: "", + padding: "", + border: "Width" +}, function( prefix, suffix ) { + jQuery.cssHooks[ prefix + suffix ] = { + expand: function( value ) { + var i = 0, + expanded = {}, + + // Assumes a single number if not a string + parts = typeof value === "string" ? value.split( " " ) : [ value ]; + + for ( ; i < 4; i++ ) { + expanded[ prefix + cssExpand[ i ] + suffix ] = + parts[ i ] || parts[ i - 2 ] || parts[ 0 ]; + } + + return expanded; + } + }; + + if ( prefix !== "margin" ) { + jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber; + } +} ); + +jQuery.fn.extend( { + css: function( name, value ) { + return access( this, function( elem, name, value ) { + var styles, len, + map = {}, + i = 0; + + if ( Array.isArray( name ) ) { + styles = getStyles( elem ); + len = name.length; + + for ( ; i < len; i++ ) { + map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles ); + } + + return map; + } + + return value !== undefined ? + jQuery.style( elem, name, value ) : + jQuery.css( elem, name ); + }, name, value, arguments.length > 1 ); + } +} ); + + +function Tween( elem, options, prop, end, easing ) { + return new Tween.prototype.init( elem, options, prop, end, easing ); +} +jQuery.Tween = Tween; + +Tween.prototype = { + constructor: Tween, + init: function( elem, options, prop, end, easing, unit ) { + this.elem = elem; + this.prop = prop; + this.easing = easing || jQuery.easing._default; + this.options = options; + this.start = this.now = this.cur(); + this.end = end; + this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" ); + }, + cur: function() { + var hooks = Tween.propHooks[ this.prop ]; + + return hooks && hooks.get ? + hooks.get( this ) : + Tween.propHooks._default.get( this ); + }, + run: function( percent ) { + var eased, + hooks = Tween.propHooks[ this.prop ]; + + if ( this.options.duration ) { + this.pos = eased = jQuery.easing[ this.easing ]( + percent, this.options.duration * percent, 0, 1, this.options.duration + ); + } else { + this.pos = eased = percent; + } + this.now = ( this.end - this.start ) * eased + this.start; + + if ( this.options.step ) { + this.options.step.call( this.elem, this.now, this ); + } + + if ( hooks && hooks.set ) { + hooks.set( this ); + } else { + Tween.propHooks._default.set( this ); + } + return this; + } +}; + +Tween.prototype.init.prototype = Tween.prototype; + +Tween.propHooks = { + _default: { + get: function( tween ) { + var result; + + // Use a property on the element directly when it is not a DOM element, + // or when there is no matching style property that exists. + if ( tween.elem.nodeType !== 1 || + tween.elem[ tween.prop ] != null && tween.elem.style[ tween.prop ] == null ) { + return tween.elem[ tween.prop ]; + } + + // Passing an empty string as a 3rd parameter to .css will automatically + // attempt a parseFloat and fallback to a string if the parse fails. + // Simple values such as "10px" are parsed to Float; + // complex values such as "rotate(1rad)" are returned as-is. + result = jQuery.css( tween.elem, tween.prop, "" ); + + // Empty strings, null, undefined and "auto" are converted to 0. + return !result || result === "auto" ? 0 : result; + }, + set: function( tween ) { + + // Use step hook for back compat. + // Use cssHook if its there. + // Use .style if available and use plain properties where available. + if ( jQuery.fx.step[ tween.prop ] ) { + jQuery.fx.step[ tween.prop ]( tween ); + } else if ( tween.elem.nodeType === 1 && ( + jQuery.cssHooks[ tween.prop ] || + tween.elem.style[ finalPropName( tween.prop ) ] != null ) ) { + jQuery.style( tween.elem, tween.prop, tween.now + tween.unit ); + } else { + tween.elem[ tween.prop ] = tween.now; + } + } + } +}; + +// Support: IE <=9 only +// Panic based approach to setting things on disconnected nodes +Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = { + set: function( tween ) { + if ( tween.elem.nodeType && tween.elem.parentNode ) { + tween.elem[ tween.prop ] = tween.now; + } + } +}; + +jQuery.easing = { + linear: function( p ) { + return p; + }, + swing: function( p ) { + return 0.5 - Math.cos( p * Math.PI ) / 2; + }, + _default: "swing" +}; + +jQuery.fx = Tween.prototype.init; + +// Back compat <1.8 extension point +jQuery.fx.step = {}; + + + + +var + fxNow, inProgress, + rfxtypes = /^(?:toggle|show|hide)$/, + rrun = /queueHooks$/; + +function schedule() { + if ( inProgress ) { + if ( document.hidden === false && window.requestAnimationFrame ) { + window.requestAnimationFrame( schedule ); + } else { + window.setTimeout( schedule, jQuery.fx.interval ); + } + + jQuery.fx.tick(); + } +} + +// Animations created synchronously will run synchronously +function createFxNow() { + window.setTimeout( function() { + fxNow = undefined; + } ); + return ( fxNow = Date.now() ); +} + +// Generate parameters to create a standard animation +function genFx( type, includeWidth ) { + var which, + i = 0, + attrs = { height: type }; + + // If we include width, step value is 1 to do all cssExpand values, + // otherwise step value is 2 to skip over Left and Right + includeWidth = includeWidth ? 1 : 0; + for ( ; i < 4; i += 2 - includeWidth ) { + which = cssExpand[ i ]; + attrs[ "margin" + which ] = attrs[ "padding" + which ] = type; + } + + if ( includeWidth ) { + attrs.opacity = attrs.width = type; + } + + return attrs; +} + +function createTween( value, prop, animation ) { + var tween, + collection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ "*" ] ), + index = 0, + length = collection.length; + for ( ; index < length; index++ ) { + if ( ( tween = collection[ index ].call( animation, prop, value ) ) ) { + + // We're done with this property + return tween; + } + } +} + +function defaultPrefilter( elem, props, opts ) { + var prop, value, toggle, hooks, oldfire, propTween, restoreDisplay, display, + isBox = "width" in props || "height" in props, + anim = this, + orig = {}, + style = elem.style, + hidden = elem.nodeType && isHiddenWithinTree( elem ), + dataShow = dataPriv.get( elem, "fxshow" ); + + // Queue-skipping animations hijack the fx hooks + if ( !opts.queue ) { + hooks = jQuery._queueHooks( elem, "fx" ); + if ( hooks.unqueued == null ) { + hooks.unqueued = 0; + oldfire = hooks.empty.fire; + hooks.empty.fire = function() { + if ( !hooks.unqueued ) { + oldfire(); + } + }; + } + hooks.unqueued++; + + anim.always( function() { + + // Ensure the complete handler is called before this completes + anim.always( function() { + hooks.unqueued--; + if ( !jQuery.queue( elem, "fx" ).length ) { + hooks.empty.fire(); + } + } ); + } ); + } + + // Detect show/hide animations + for ( prop in props ) { + value = props[ prop ]; + if ( rfxtypes.test( value ) ) { + delete props[ prop ]; + toggle = toggle || value === "toggle"; + if ( value === ( hidden ? "hide" : "show" ) ) { + + // Pretend to be hidden if this is a "show" and + // there is still data from a stopped show/hide + if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) { + hidden = true; + + // Ignore all other no-op show/hide data + } else { + continue; + } + } + orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop ); + } + } + + // Bail out if this is a no-op like .hide().hide() + propTween = !jQuery.isEmptyObject( props ); + if ( !propTween && jQuery.isEmptyObject( orig ) ) { + return; + } + + // Restrict "overflow" and "display" styles during box animations + if ( isBox && elem.nodeType === 1 ) { + + // Support: IE <=9 - 11, Edge 12 - 15 + // Record all 3 overflow attributes because IE does not infer the shorthand + // from identically-valued overflowX and overflowY and Edge just mirrors + // the overflowX value there. + opts.overflow = [ style.overflow, style.overflowX, style.overflowY ]; + + // Identify a display type, preferring old show/hide data over the CSS cascade + restoreDisplay = dataShow && dataShow.display; + if ( restoreDisplay == null ) { + restoreDisplay = dataPriv.get( elem, "display" ); + } + display = jQuery.css( elem, "display" ); + if ( display === "none" ) { + if ( restoreDisplay ) { + display = restoreDisplay; + } else { + + // Get nonempty value(s) by temporarily forcing visibility + showHide( [ elem ], true ); + restoreDisplay = elem.style.display || restoreDisplay; + display = jQuery.css( elem, "display" ); + showHide( [ elem ] ); + } + } + + // Animate inline elements as inline-block + if ( display === "inline" || display === "inline-block" && restoreDisplay != null ) { + if ( jQuery.css( elem, "float" ) === "none" ) { + + // Restore the original display value at the end of pure show/hide animations + if ( !propTween ) { + anim.done( function() { + style.display = restoreDisplay; + } ); + if ( restoreDisplay == null ) { + display = style.display; + restoreDisplay = display === "none" ? "" : display; + } + } + style.display = "inline-block"; + } + } + } + + if ( opts.overflow ) { + style.overflow = "hidden"; + anim.always( function() { + style.overflow = opts.overflow[ 0 ]; + style.overflowX = opts.overflow[ 1 ]; + style.overflowY = opts.overflow[ 2 ]; + } ); + } + + // Implement show/hide animations + propTween = false; + for ( prop in orig ) { + + // General show/hide setup for this element animation + if ( !propTween ) { + if ( dataShow ) { + if ( "hidden" in dataShow ) { + hidden = dataShow.hidden; + } + } else { + dataShow = dataPriv.access( elem, "fxshow", { display: restoreDisplay } ); + } + + // Store hidden/visible for toggle so `.stop().toggle()` "reverses" + if ( toggle ) { + dataShow.hidden = !hidden; + } + + // Show elements before animating them + if ( hidden ) { + showHide( [ elem ], true ); + } + + /* eslint-disable no-loop-func */ + + anim.done( function() { + + /* eslint-enable no-loop-func */ + + // The final step of a "hide" animation is actually hiding the element + if ( !hidden ) { + showHide( [ elem ] ); + } + dataPriv.remove( elem, "fxshow" ); + for ( prop in orig ) { + jQuery.style( elem, prop, orig[ prop ] ); + } + } ); + } + + // Per-property setup + propTween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim ); + if ( !( prop in dataShow ) ) { + dataShow[ prop ] = propTween.start; + if ( hidden ) { + propTween.end = propTween.start; + propTween.start = 0; + } + } + } +} + +function propFilter( props, specialEasing ) { + var index, name, easing, value, hooks; + + // camelCase, specialEasing and expand cssHook pass + for ( index in props ) { + name = camelCase( index ); + easing = specialEasing[ name ]; + value = props[ index ]; + if ( Array.isArray( value ) ) { + easing = value[ 1 ]; + value = props[ index ] = value[ 0 ]; + } + + if ( index !== name ) { + props[ name ] = value; + delete props[ index ]; + } + + hooks = jQuery.cssHooks[ name ]; + if ( hooks && "expand" in hooks ) { + value = hooks.expand( value ); + delete props[ name ]; + + // Not quite $.extend, this won't overwrite existing keys. + // Reusing 'index' because we have the correct "name" + for ( index in value ) { + if ( !( index in props ) ) { + props[ index ] = value[ index ]; + specialEasing[ index ] = easing; + } + } + } else { + specialEasing[ name ] = easing; + } + } +} + +function Animation( elem, properties, options ) { + var result, + stopped, + index = 0, + length = Animation.prefilters.length, + deferred = jQuery.Deferred().always( function() { + + // Don't match elem in the :animated selector + delete tick.elem; + } ), + tick = function() { + if ( stopped ) { + return false; + } + var currentTime = fxNow || createFxNow(), + remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ), + + // Support: Android 2.3 only + // Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497) + temp = remaining / animation.duration || 0, + percent = 1 - temp, + index = 0, + length = animation.tweens.length; + + for ( ; index < length; index++ ) { + animation.tweens[ index ].run( percent ); + } + + deferred.notifyWith( elem, [ animation, percent, remaining ] ); + + // If there's more to do, yield + if ( percent < 1 && length ) { + return remaining; + } + + // If this was an empty animation, synthesize a final progress notification + if ( !length ) { + deferred.notifyWith( elem, [ animation, 1, 0 ] ); + } + + // Resolve the animation and report its conclusion + deferred.resolveWith( elem, [ animation ] ); + return false; + }, + animation = deferred.promise( { + elem: elem, + props: jQuery.extend( {}, properties ), + opts: jQuery.extend( true, { + specialEasing: {}, + easing: jQuery.easing._default + }, options ), + originalProperties: properties, + originalOptions: options, + startTime: fxNow || createFxNow(), + duration: options.duration, + tweens: [], + createTween: function( prop, end ) { + var tween = jQuery.Tween( elem, animation.opts, prop, end, + animation.opts.specialEasing[ prop ] || animation.opts.easing ); + animation.tweens.push( tween ); + return tween; + }, + stop: function( gotoEnd ) { + var index = 0, + + // If we are going to the end, we want to run all the tweens + // otherwise we skip this part + length = gotoEnd ? animation.tweens.length : 0; + if ( stopped ) { + return this; + } + stopped = true; + for ( ; index < length; index++ ) { + animation.tweens[ index ].run( 1 ); + } + + // Resolve when we played the last frame; otherwise, reject + if ( gotoEnd ) { + deferred.notifyWith( elem, [ animation, 1, 0 ] ); + deferred.resolveWith( elem, [ animation, gotoEnd ] ); + } else { + deferred.rejectWith( elem, [ animation, gotoEnd ] ); + } + return this; + } + } ), + props = animation.props; + + propFilter( props, animation.opts.specialEasing ); + + for ( ; index < length; index++ ) { + result = Animation.prefilters[ index ].call( animation, elem, props, animation.opts ); + if ( result ) { + if ( isFunction( result.stop ) ) { + jQuery._queueHooks( animation.elem, animation.opts.queue ).stop = + result.stop.bind( result ); + } + return result; + } + } + + jQuery.map( props, createTween, animation ); + + if ( isFunction( animation.opts.start ) ) { + animation.opts.start.call( elem, animation ); + } + + // Attach callbacks from options + animation + .progress( animation.opts.progress ) + .done( animation.opts.done, animation.opts.complete ) + .fail( animation.opts.fail ) + .always( animation.opts.always ); + + jQuery.fx.timer( + jQuery.extend( tick, { + elem: elem, + anim: animation, + queue: animation.opts.queue + } ) + ); + + return animation; +} + +jQuery.Animation = jQuery.extend( Animation, { + + tweeners: { + "*": [ function( prop, value ) { + var tween = this.createTween( prop, value ); + adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween ); + return tween; + } ] + }, + + tweener: function( props, callback ) { + if ( isFunction( props ) ) { + callback = props; + props = [ "*" ]; + } else { + props = props.match( rnothtmlwhite ); + } + + var prop, + index = 0, + length = props.length; + + for ( ; index < length; index++ ) { + prop = props[ index ]; + Animation.tweeners[ prop ] = Animation.tweeners[ prop ] || []; + Animation.tweeners[ prop ].unshift( callback ); + } + }, + + prefilters: [ defaultPrefilter ], + + prefilter: function( callback, prepend ) { + if ( prepend ) { + Animation.prefilters.unshift( callback ); + } else { + Animation.prefilters.push( callback ); + } + } +} ); + +jQuery.speed = function( speed, easing, fn ) { + var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : { + complete: fn || !fn && easing || + isFunction( speed ) && speed, + duration: speed, + easing: fn && easing || easing && !isFunction( easing ) && easing + }; + + // Go to the end state if fx are off + if ( jQuery.fx.off ) { + opt.duration = 0; + + } else { + if ( typeof opt.duration !== "number" ) { + if ( opt.duration in jQuery.fx.speeds ) { + opt.duration = jQuery.fx.speeds[ opt.duration ]; + + } else { + opt.duration = jQuery.fx.speeds._default; + } + } + } + + // Normalize opt.queue - true/undefined/null -> "fx" + if ( opt.queue == null || opt.queue === true ) { + opt.queue = "fx"; + } + + // Queueing + opt.old = opt.complete; + + opt.complete = function() { + if ( isFunction( opt.old ) ) { + opt.old.call( this ); + } + + if ( opt.queue ) { + jQuery.dequeue( this, opt.queue ); + } + }; + + return opt; +}; + +jQuery.fn.extend( { + fadeTo: function( speed, to, easing, callback ) { + + // Show any hidden elements after setting opacity to 0 + return this.filter( isHiddenWithinTree ).css( "opacity", 0 ).show() + + // Animate to the value specified + .end().animate( { opacity: to }, speed, easing, callback ); + }, + animate: function( prop, speed, easing, callback ) { + var empty = jQuery.isEmptyObject( prop ), + optall = jQuery.speed( speed, easing, callback ), + doAnimation = function() { + + // Operate on a copy of prop so per-property easing won't be lost + var anim = Animation( this, jQuery.extend( {}, prop ), optall ); + + // Empty animations, or finishing resolves immediately + if ( empty || dataPriv.get( this, "finish" ) ) { + anim.stop( true ); + } + }; + + doAnimation.finish = doAnimation; + + return empty || optall.queue === false ? + this.each( doAnimation ) : + this.queue( optall.queue, doAnimation ); + }, + stop: function( type, clearQueue, gotoEnd ) { + var stopQueue = function( hooks ) { + var stop = hooks.stop; + delete hooks.stop; + stop( gotoEnd ); + }; + + if ( typeof type !== "string" ) { + gotoEnd = clearQueue; + clearQueue = type; + type = undefined; + } + if ( clearQueue ) { + this.queue( type || "fx", [] ); + } + + return this.each( function() { + var dequeue = true, + index = type != null && type + "queueHooks", + timers = jQuery.timers, + data = dataPriv.get( this ); + + if ( index ) { + if ( data[ index ] && data[ index ].stop ) { + stopQueue( data[ index ] ); + } + } else { + for ( index in data ) { + if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) { + stopQueue( data[ index ] ); + } + } + } + + for ( index = timers.length; index--; ) { + if ( timers[ index ].elem === this && + ( type == null || timers[ index ].queue === type ) ) { + + timers[ index ].anim.stop( gotoEnd ); + dequeue = false; + timers.splice( index, 1 ); + } + } + + // Start the next in the queue if the last step wasn't forced. + // Timers currently will call their complete callbacks, which + // will dequeue but only if they were gotoEnd. + if ( dequeue || !gotoEnd ) { + jQuery.dequeue( this, type ); + } + } ); + }, + finish: function( type ) { + if ( type !== false ) { + type = type || "fx"; + } + return this.each( function() { + var index, + data = dataPriv.get( this ), + queue = data[ type + "queue" ], + hooks = data[ type + "queueHooks" ], + timers = jQuery.timers, + length = queue ? queue.length : 0; + + // Enable finishing flag on private data + data.finish = true; + + // Empty the queue first + jQuery.queue( this, type, [] ); + + if ( hooks && hooks.stop ) { + hooks.stop.call( this, true ); + } + + // Look for any active animations, and finish them + for ( index = timers.length; index--; ) { + if ( timers[ index ].elem === this && timers[ index ].queue === type ) { + timers[ index ].anim.stop( true ); + timers.splice( index, 1 ); + } + } + + // Look for any animations in the old queue and finish them + for ( index = 0; index < length; index++ ) { + if ( queue[ index ] && queue[ index ].finish ) { + queue[ index ].finish.call( this ); + } + } + + // Turn off finishing flag + delete data.finish; + } ); + } +} ); + +jQuery.each( [ "toggle", "show", "hide" ], function( _i, name ) { + var cssFn = jQuery.fn[ name ]; + jQuery.fn[ name ] = function( speed, easing, callback ) { + return speed == null || typeof speed === "boolean" ? + cssFn.apply( this, arguments ) : + this.animate( genFx( name, true ), speed, easing, callback ); + }; +} ); + +// Generate shortcuts for custom animations +jQuery.each( { + slideDown: genFx( "show" ), + slideUp: genFx( "hide" ), + slideToggle: genFx( "toggle" ), + fadeIn: { opacity: "show" }, + fadeOut: { opacity: "hide" }, + fadeToggle: { opacity: "toggle" } +}, function( name, props ) { + jQuery.fn[ name ] = function( speed, easing, callback ) { + return this.animate( props, speed, easing, callback ); + }; +} ); + +jQuery.timers = []; +jQuery.fx.tick = function() { + var timer, + i = 0, + timers = jQuery.timers; + + fxNow = Date.now(); + + for ( ; i < timers.length; i++ ) { + timer = timers[ i ]; + + // Run the timer and safely remove it when done (allowing for external removal) + if ( !timer() && timers[ i ] === timer ) { + timers.splice( i--, 1 ); + } + } + + if ( !timers.length ) { + jQuery.fx.stop(); + } + fxNow = undefined; +}; + +jQuery.fx.timer = function( timer ) { + jQuery.timers.push( timer ); + jQuery.fx.start(); +}; + +jQuery.fx.interval = 13; +jQuery.fx.start = function() { + if ( inProgress ) { + return; + } + + inProgress = true; + schedule(); +}; + +jQuery.fx.stop = function() { + inProgress = null; +}; + +jQuery.fx.speeds = { + slow: 600, + fast: 200, + + // Default speed + _default: 400 +}; + + +// Based off of the plugin by Clint Helfers, with permission. +// https://web.archive.org/web/20100324014747/http://blindsignals.com/index.php/2009/07/jquery-delay/ +jQuery.fn.delay = function( time, type ) { + time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; + type = type || "fx"; + + return this.queue( type, function( next, hooks ) { + var timeout = window.setTimeout( next, time ); + hooks.stop = function() { + window.clearTimeout( timeout ); + }; + } ); +}; + + +( function() { + var input = document.createElement( "input" ), + select = document.createElement( "select" ), + opt = select.appendChild( document.createElement( "option" ) ); + + input.type = "checkbox"; + + // Support: Android <=4.3 only + // Default value for a checkbox should be "on" + support.checkOn = input.value !== ""; + + // Support: IE <=11 only + // Must access selectedIndex to make default options select + support.optSelected = opt.selected; + + // Support: IE <=11 only + // An input loses its value after becoming a radio + input = document.createElement( "input" ); + input.value = "t"; + input.type = "radio"; + support.radioValue = input.value === "t"; +} )(); + + +var boolHook, + attrHandle = jQuery.expr.attrHandle; + +jQuery.fn.extend( { + attr: function( name, value ) { + return access( this, jQuery.attr, name, value, arguments.length > 1 ); + }, + + removeAttr: function( name ) { + return this.each( function() { + jQuery.removeAttr( this, name ); + } ); + } +} ); + +jQuery.extend( { + attr: function( elem, name, value ) { + var ret, hooks, + nType = elem.nodeType; + + // Don't get/set attributes on text, comment and attribute nodes + if ( nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + // Fallback to prop when attributes are not supported + if ( typeof elem.getAttribute === "undefined" ) { + return jQuery.prop( elem, name, value ); + } + + // Attribute hooks are determined by the lowercase version + // Grab necessary hook if one is defined + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + hooks = jQuery.attrHooks[ name.toLowerCase() ] || + ( jQuery.expr.match.bool.test( name ) ? boolHook : undefined ); + } + + if ( value !== undefined ) { + if ( value === null ) { + jQuery.removeAttr( elem, name ); + return; + } + + if ( hooks && "set" in hooks && + ( ret = hooks.set( elem, value, name ) ) !== undefined ) { + return ret; + } + + elem.setAttribute( name, value + "" ); + return value; + } + + if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { + return ret; + } + + ret = jQuery.find.attr( elem, name ); + + // Non-existent attributes return null, we normalize to undefined + return ret == null ? undefined : ret; + }, + + attrHooks: { + type: { + set: function( elem, value ) { + if ( !support.radioValue && value === "radio" && + nodeName( elem, "input" ) ) { + var val = elem.value; + elem.setAttribute( "type", value ); + if ( val ) { + elem.value = val; + } + return value; + } + } + } + }, + + removeAttr: function( elem, value ) { + var name, + i = 0, + + // Attribute names can contain non-HTML whitespace characters + // https://html.spec.whatwg.org/multipage/syntax.html#attributes-2 + attrNames = value && value.match( rnothtmlwhite ); + + if ( attrNames && elem.nodeType === 1 ) { + while ( ( name = attrNames[ i++ ] ) ) { + elem.removeAttribute( name ); + } + } + } +} ); + +// Hooks for boolean attributes +boolHook = { + set: function( elem, value, name ) { + if ( value === false ) { + + // Remove boolean attributes when set to false + jQuery.removeAttr( elem, name ); + } else { + elem.setAttribute( name, name ); + } + return name; + } +}; + +jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( _i, name ) { + var getter = attrHandle[ name ] || jQuery.find.attr; + + attrHandle[ name ] = function( elem, name, isXML ) { + var ret, handle, + lowercaseName = name.toLowerCase(); + + if ( !isXML ) { + + // Avoid an infinite loop by temporarily removing this function from the getter + handle = attrHandle[ lowercaseName ]; + attrHandle[ lowercaseName ] = ret; + ret = getter( elem, name, isXML ) != null ? + lowercaseName : + null; + attrHandle[ lowercaseName ] = handle; + } + return ret; + }; +} ); + + + + +var rfocusable = /^(?:input|select|textarea|button)$/i, + rclickable = /^(?:a|area)$/i; + +jQuery.fn.extend( { + prop: function( name, value ) { + return access( this, jQuery.prop, name, value, arguments.length > 1 ); + }, + + removeProp: function( name ) { + return this.each( function() { + delete this[ jQuery.propFix[ name ] || name ]; + } ); + } +} ); + +jQuery.extend( { + prop: function( elem, name, value ) { + var ret, hooks, + nType = elem.nodeType; + + // Don't get/set properties on text, comment and attribute nodes + if ( nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + + // Fix name and attach hooks + name = jQuery.propFix[ name ] || name; + hooks = jQuery.propHooks[ name ]; + } + + if ( value !== undefined ) { + if ( hooks && "set" in hooks && + ( ret = hooks.set( elem, value, name ) ) !== undefined ) { + return ret; + } + + return ( elem[ name ] = value ); + } + + if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) { + return ret; + } + + return elem[ name ]; + }, + + propHooks: { + tabIndex: { + get: function( elem ) { + + // Support: IE <=9 - 11 only + // elem.tabIndex doesn't always return the + // correct value when it hasn't been explicitly set + // https://web.archive.org/web/20141116233347/http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ + // Use proper attribute retrieval(#12072) + var tabindex = jQuery.find.attr( elem, "tabindex" ); + + if ( tabindex ) { + return parseInt( tabindex, 10 ); + } + + if ( + rfocusable.test( elem.nodeName ) || + rclickable.test( elem.nodeName ) && + elem.href + ) { + return 0; + } + + return -1; + } + } + }, + + propFix: { + "for": "htmlFor", + "class": "className" + } +} ); + +// Support: IE <=11 only +// Accessing the selectedIndex property +// forces the browser to respect setting selected +// on the option +// The getter ensures a default option is selected +// when in an optgroup +// eslint rule "no-unused-expressions" is disabled for this code +// since it considers such accessions noop +if ( !support.optSelected ) { + jQuery.propHooks.selected = { + get: function( elem ) { + + /* eslint no-unused-expressions: "off" */ + + var parent = elem.parentNode; + if ( parent && parent.parentNode ) { + parent.parentNode.selectedIndex; + } + return null; + }, + set: function( elem ) { + + /* eslint no-unused-expressions: "off" */ + + var parent = elem.parentNode; + if ( parent ) { + parent.selectedIndex; + + if ( parent.parentNode ) { + parent.parentNode.selectedIndex; + } + } + } + }; +} + +jQuery.each( [ + "tabIndex", + "readOnly", + "maxLength", + "cellSpacing", + "cellPadding", + "rowSpan", + "colSpan", + "useMap", + "frameBorder", + "contentEditable" +], function() { + jQuery.propFix[ this.toLowerCase() ] = this; +} ); + + + + + // Strip and collapse whitespace according to HTML spec + // https://infra.spec.whatwg.org/#strip-and-collapse-ascii-whitespace + function stripAndCollapse( value ) { + var tokens = value.match( rnothtmlwhite ) || []; + return tokens.join( " " ); + } + + +function getClass( elem ) { + return elem.getAttribute && elem.getAttribute( "class" ) || ""; +} + +function classesToArray( value ) { + if ( Array.isArray( value ) ) { + return value; + } + if ( typeof value === "string" ) { + return value.match( rnothtmlwhite ) || []; + } + return []; +} + +jQuery.fn.extend( { + addClass: function( value ) { + var classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).addClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + classes = classesToArray( value ); + + if ( classes.length ) { + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + if ( cur.indexOf( " " + clazz + " " ) < 0 ) { + cur += clazz + " "; + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + removeClass: function( value ) { + var classes, elem, cur, curValue, clazz, j, finalValue, + i = 0; + + if ( isFunction( value ) ) { + return this.each( function( j ) { + jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) ); + } ); + } + + if ( !arguments.length ) { + return this.attr( "class", "" ); + } + + classes = classesToArray( value ); + + if ( classes.length ) { + while ( ( elem = this[ i++ ] ) ) { + curValue = getClass( elem ); + + // This expression is here for better compressibility (see addClass) + cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + + if ( cur ) { + j = 0; + while ( ( clazz = classes[ j++ ] ) ) { + + // Remove *all* instances + while ( cur.indexOf( " " + clazz + " " ) > -1 ) { + cur = cur.replace( " " + clazz + " ", " " ); + } + } + + // Only assign if different to avoid unneeded rendering. + finalValue = stripAndCollapse( cur ); + if ( curValue !== finalValue ) { + elem.setAttribute( "class", finalValue ); + } + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value, + isValidValue = type === "string" || Array.isArray( value ); + + if ( typeof stateVal === "boolean" && isValidValue ) { + return stateVal ? this.addClass( value ) : this.removeClass( value ); + } + + if ( isFunction( value ) ) { + return this.each( function( i ) { + jQuery( this ).toggleClass( + value.call( this, i, getClass( this ), stateVal ), + stateVal + ); + } ); + } + + return this.each( function() { + var className, i, self, classNames; + + if ( isValidValue ) { + + // Toggle individual class names + i = 0; + self = jQuery( this ); + classNames = classesToArray( value ); + + while ( ( className = classNames[ i++ ] ) ) { + + // Check each className given, space separated list + if ( self.hasClass( className ) ) { + self.removeClass( className ); + } else { + self.addClass( className ); + } + } + + // Toggle whole class name + } else if ( value === undefined || type === "boolean" ) { + className = getClass( this ); + if ( className ) { + + // Store className if set + dataPriv.set( this, "__className__", className ); + } + + // If the element has a class name or if we're passed `false`, + // then remove the whole classname (if there was one, the above saved it). + // Otherwise bring back whatever was previously saved (if anything), + // falling back to the empty string if nothing was stored. + if ( this.setAttribute ) { + this.setAttribute( "class", + className || value === false ? + "" : + dataPriv.get( this, "__className__" ) || "" + ); + } + } + } ); + }, + + hasClass: function( selector ) { + var className, elem, + i = 0; + + className = " " + selector + " "; + while ( ( elem = this[ i++ ] ) ) { + if ( elem.nodeType === 1 && + ( " " + stripAndCollapse( getClass( elem ) ) + " " ).indexOf( className ) > -1 ) { + return true; + } + } + + return false; + } +} ); + + + + +var rreturn = /\r/g; + +jQuery.fn.extend( { + val: function( value ) { + var hooks, ret, valueIsFunction, + elem = this[ 0 ]; + + if ( !arguments.length ) { + if ( elem ) { + hooks = jQuery.valHooks[ elem.type ] || + jQuery.valHooks[ elem.nodeName.toLowerCase() ]; + + if ( hooks && + "get" in hooks && + ( ret = hooks.get( elem, "value" ) ) !== undefined + ) { + return ret; + } + + ret = elem.value; + + // Handle most common string cases + if ( typeof ret === "string" ) { + return ret.replace( rreturn, "" ); + } + + // Handle cases where value is null/undef or number + return ret == null ? "" : ret; + } + + return; + } + + valueIsFunction = isFunction( value ); + + return this.each( function( i ) { + var val; + + if ( this.nodeType !== 1 ) { + return; + } + + if ( valueIsFunction ) { + val = value.call( this, i, jQuery( this ).val() ); + } else { + val = value; + } + + // Treat null/undefined as ""; convert numbers to string + if ( val == null ) { + val = ""; + + } else if ( typeof val === "number" ) { + val += ""; + + } else if ( Array.isArray( val ) ) { + val = jQuery.map( val, function( value ) { + return value == null ? "" : value + ""; + } ); + } + + hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; + + // If set returns undefined, fall back to normal setting + if ( !hooks || !( "set" in hooks ) || hooks.set( this, val, "value" ) === undefined ) { + this.value = val; + } + } ); + } +} ); + +jQuery.extend( { + valHooks: { + option: { + get: function( elem ) { + + var val = jQuery.find.attr( elem, "value" ); + return val != null ? + val : + + // Support: IE <=10 - 11 only + // option.text throws exceptions (#14686, #14858) + // Strip and collapse whitespace + // https://html.spec.whatwg.org/#strip-and-collapse-whitespace + stripAndCollapse( jQuery.text( elem ) ); + } + }, + select: { + get: function( elem ) { + var value, option, i, + options = elem.options, + index = elem.selectedIndex, + one = elem.type === "select-one", + values = one ? null : [], + max = one ? index + 1 : options.length; + + if ( index < 0 ) { + i = max; + + } else { + i = one ? index : 0; + } + + // Loop through all the selected options + for ( ; i < max; i++ ) { + option = options[ i ]; + + // Support: IE <=9 only + // IE8-9 doesn't update selected after form reset (#2551) + if ( ( option.selected || i === index ) && + + // Don't return options that are disabled or in a disabled optgroup + !option.disabled && + ( !option.parentNode.disabled || + !nodeName( option.parentNode, "optgroup" ) ) ) { + + // Get the specific value for the option + value = jQuery( option ).val(); + + // We don't need an array for one selects + if ( one ) { + return value; + } + + // Multi-Selects return an array + values.push( value ); + } + } + + return values; + }, + + set: function( elem, value ) { + var optionSet, option, + options = elem.options, + values = jQuery.makeArray( value ), + i = options.length; + + while ( i-- ) { + option = options[ i ]; + + /* eslint-disable no-cond-assign */ + + if ( option.selected = + jQuery.inArray( jQuery.valHooks.option.get( option ), values ) > -1 + ) { + optionSet = true; + } + + /* eslint-enable no-cond-assign */ + } + + // Force browsers to behave consistently when non-matching value is set + if ( !optionSet ) { + elem.selectedIndex = -1; + } + return values; + } + } + } +} ); + +// Radios and checkboxes getter/setter +jQuery.each( [ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = { + set: function( elem, value ) { + if ( Array.isArray( value ) ) { + return ( elem.checked = jQuery.inArray( jQuery( elem ).val(), value ) > -1 ); + } + } + }; + if ( !support.checkOn ) { + jQuery.valHooks[ this ].get = function( elem ) { + return elem.getAttribute( "value" ) === null ? "on" : elem.value; + }; + } +} ); + + + + +// Return jQuery for attributes-only inclusion + + +support.focusin = "onfocusin" in window; + + +var rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, + stopPropagationCallback = function( e ) { + e.stopPropagation(); + }; + +jQuery.extend( jQuery.event, { + + trigger: function( event, data, elem, onlyHandlers ) { + + var i, cur, tmp, bubbleType, ontype, handle, special, lastElement, + eventPath = [ elem || document ], + type = hasOwn.call( event, "type" ) ? event.type : event, + namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split( "." ) : []; + + cur = lastElement = tmp = elem = elem || document; + + // Don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + // focus/blur morphs to focusin/out; ensure we're not firing them right now + if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { + return; + } + + if ( type.indexOf( "." ) > -1 ) { + + // Namespaced trigger; create a regexp to match event type in handle() + namespaces = type.split( "." ); + type = namespaces.shift(); + namespaces.sort(); + } + ontype = type.indexOf( ":" ) < 0 && "on" + type; + + // Caller can pass in a jQuery.Event object, Object, or just an event type string + event = event[ jQuery.expando ] ? + event : + new jQuery.Event( type, typeof event === "object" && event ); + + // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) + event.isTrigger = onlyHandlers ? 2 : 3; + event.namespace = namespaces.join( "." ); + event.rnamespace = event.namespace ? + new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ) : + null; + + // Clean up the event in case it is being reused + event.result = undefined; + if ( !event.target ) { + event.target = elem; + } + + // Clone any incoming data and prepend the event, creating the handler arg list + data = data == null ? + [ event ] : + jQuery.makeArray( data, [ event ] ); + + // Allow special events to draw outside the lines + special = jQuery.event.special[ type ] || {}; + if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { + return; + } + + // Determine event propagation path in advance, per W3C events spec (#9951) + // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) + if ( !onlyHandlers && !special.noBubble && !isWindow( elem ) ) { + + bubbleType = special.delegateType || type; + if ( !rfocusMorph.test( bubbleType + type ) ) { + cur = cur.parentNode; + } + for ( ; cur; cur = cur.parentNode ) { + eventPath.push( cur ); + tmp = cur; + } + + // Only add window if we got to document (e.g., not plain obj or detached DOM) + if ( tmp === ( elem.ownerDocument || document ) ) { + eventPath.push( tmp.defaultView || tmp.parentWindow || window ); + } + } + + // Fire handlers on the event path + i = 0; + while ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) { + lastElement = cur; + event.type = i > 1 ? + bubbleType : + special.bindType || type; + + // jQuery handler + handle = ( dataPriv.get( cur, "events" ) || Object.create( null ) )[ event.type ] && + dataPriv.get( cur, "handle" ); + if ( handle ) { + handle.apply( cur, data ); + } + + // Native handler + handle = ontype && cur[ ontype ]; + if ( handle && handle.apply && acceptData( cur ) ) { + event.result = handle.apply( cur, data ); + if ( event.result === false ) { + event.preventDefault(); + } + } + } + event.type = type; + + // If nobody prevented the default action, do it now + if ( !onlyHandlers && !event.isDefaultPrevented() ) { + + if ( ( !special._default || + special._default.apply( eventPath.pop(), data ) === false ) && + acceptData( elem ) ) { + + // Call a native DOM method on the target with the same name as the event. + // Don't do default actions on window, that's where global variables be (#6170) + if ( ontype && isFunction( elem[ type ] ) && !isWindow( elem ) ) { + + // Don't re-trigger an onFOO event when we call its FOO() method + tmp = elem[ ontype ]; + + if ( tmp ) { + elem[ ontype ] = null; + } + + // Prevent re-triggering of the same event, since we already bubbled it above + jQuery.event.triggered = type; + + if ( event.isPropagationStopped() ) { + lastElement.addEventListener( type, stopPropagationCallback ); + } + + elem[ type ](); + + if ( event.isPropagationStopped() ) { + lastElement.removeEventListener( type, stopPropagationCallback ); + } + + jQuery.event.triggered = undefined; + + if ( tmp ) { + elem[ ontype ] = tmp; + } + } + } + } + + return event.result; + }, + + // Piggyback on a donor event to simulate a different one + // Used only for `focus(in | out)` events + simulate: function( type, elem, event ) { + var e = jQuery.extend( + new jQuery.Event(), + event, + { + type: type, + isSimulated: true + } + ); + + jQuery.event.trigger( e, null, elem ); + } + +} ); + +jQuery.fn.extend( { + + trigger: function( type, data ) { + return this.each( function() { + jQuery.event.trigger( type, data, this ); + } ); + }, + triggerHandler: function( type, data ) { + var elem = this[ 0 ]; + if ( elem ) { + return jQuery.event.trigger( type, data, elem, true ); + } + } +} ); + + +// Support: Firefox <=44 +// Firefox doesn't have focus(in | out) events +// Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787 +// +// Support: Chrome <=48 - 49, Safari <=9.0 - 9.1 +// focus(in | out) events fire after focus & blur events, +// which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order +// Related ticket - https://bugs.chromium.org/p/chromium/issues/detail?id=449857 +if ( !support.focusin ) { + jQuery.each( { focus: "focusin", blur: "focusout" }, function( orig, fix ) { + + // Attach a single capturing handler on the document while someone wants focusin/focusout + var handler = function( event ) { + jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) ); + }; + + jQuery.event.special[ fix ] = { + setup: function() { + + // Handle: regular nodes (via `this.ownerDocument`), window + // (via `this.document`) & document (via `this`). + var doc = this.ownerDocument || this.document || this, + attaches = dataPriv.access( doc, fix ); + + if ( !attaches ) { + doc.addEventListener( orig, handler, true ); + } + dataPriv.access( doc, fix, ( attaches || 0 ) + 1 ); + }, + teardown: function() { + var doc = this.ownerDocument || this.document || this, + attaches = dataPriv.access( doc, fix ) - 1; + + if ( !attaches ) { + doc.removeEventListener( orig, handler, true ); + dataPriv.remove( doc, fix ); + + } else { + dataPriv.access( doc, fix, attaches ); + } + } + }; + } ); +} +var location = window.location; + +var nonce = { guid: Date.now() }; + +var rquery = ( /\?/ ); + + + +// Cross-browser xml parsing +jQuery.parseXML = function( data ) { + var xml, parserErrorElem; + if ( !data || typeof data !== "string" ) { + return null; + } + + // Support: IE 9 - 11 only + // IE throws on parseFromString with invalid input. + try { + xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" ); + } catch ( e ) {} + + parserErrorElem = xml && xml.getElementsByTagName( "parsererror" )[ 0 ]; + if ( !xml || parserErrorElem ) { + jQuery.error( "Invalid XML: " + ( + parserErrorElem ? + jQuery.map( parserErrorElem.childNodes, function( el ) { + return el.textContent; + } ).join( "\n" ) : + data + ) ); + } + return xml; +}; + + +var + rbracket = /\[\]$/, + rCRLF = /\r?\n/g, + rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i, + rsubmittable = /^(?:input|select|textarea|keygen)/i; + +function buildParams( prefix, obj, traditional, add ) { + var name; + + if ( Array.isArray( obj ) ) { + + // Serialize array item. + jQuery.each( obj, function( i, v ) { + if ( traditional || rbracket.test( prefix ) ) { + + // Treat each array item as a scalar. + add( prefix, v ); + + } else { + + // Item is non-scalar (array or object), encode its numeric index. + buildParams( + prefix + "[" + ( typeof v === "object" && v != null ? i : "" ) + "]", + v, + traditional, + add + ); + } + } ); + + } else if ( !traditional && toType( obj ) === "object" ) { + + // Serialize object item. + for ( name in obj ) { + buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add ); + } + + } else { + + // Serialize scalar item. + add( prefix, obj ); + } +} + +// Serialize an array of form elements or a set of +// key/values into a query string +jQuery.param = function( a, traditional ) { + var prefix, + s = [], + add = function( key, valueOrFunction ) { + + // If value is a function, invoke it and use its return value + var value = isFunction( valueOrFunction ) ? + valueOrFunction() : + valueOrFunction; + + s[ s.length ] = encodeURIComponent( key ) + "=" + + encodeURIComponent( value == null ? "" : value ); + }; + + if ( a == null ) { + return ""; + } + + // If an array was passed in, assume that it is an array of form elements. + if ( Array.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) { + + // Serialize the form elements + jQuery.each( a, function() { + add( this.name, this.value ); + } ); + + } else { + + // If traditional, encode the "old" way (the way 1.3.2 or older + // did it), otherwise encode params recursively. + for ( prefix in a ) { + buildParams( prefix, a[ prefix ], traditional, add ); + } + } + + // Return the resulting serialization + return s.join( "&" ); +}; + +jQuery.fn.extend( { + serialize: function() { + return jQuery.param( this.serializeArray() ); + }, + serializeArray: function() { + return this.map( function() { + + // Can add propHook for "elements" to filter or add form elements + var elements = jQuery.prop( this, "elements" ); + return elements ? jQuery.makeArray( elements ) : this; + } ).filter( function() { + var type = this.type; + + // Use .is( ":disabled" ) so that fieldset[disabled] works + return this.name && !jQuery( this ).is( ":disabled" ) && + rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) && + ( this.checked || !rcheckableType.test( type ) ); + } ).map( function( _i, elem ) { + var val = jQuery( this ).val(); + + if ( val == null ) { + return null; + } + + if ( Array.isArray( val ) ) { + return jQuery.map( val, function( val ) { + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + } ); + } + + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + } ).get(); + } +} ); + + +var + r20 = /%20/g, + rhash = /#.*$/, + rantiCache = /([?&])_=[^&]*/, + rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg, + + // #7653, #8125, #8152: local protocol detection + rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/, + rnoContent = /^(?:GET|HEAD)$/, + rprotocol = /^\/\//, + + /* Prefilters + * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example) + * 2) These are called: + * - BEFORE asking for a transport + * - AFTER param serialization (s.data is a string if s.processData is true) + * 3) key is the dataType + * 4) the catchall symbol "*" can be used + * 5) execution will start with transport dataType and THEN continue down to "*" if needed + */ + prefilters = {}, + + /* Transports bindings + * 1) key is the dataType + * 2) the catchall symbol "*" can be used + * 3) selection will start with transport dataType and THEN go to "*" if needed + */ + transports = {}, + + // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression + allTypes = "*/".concat( "*" ), + + // Anchor tag for parsing the document origin + originAnchor = document.createElement( "a" ); + +originAnchor.href = location.href; + +// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport +function addToPrefiltersOrTransports( structure ) { + + // dataTypeExpression is optional and defaults to "*" + return function( dataTypeExpression, func ) { + + if ( typeof dataTypeExpression !== "string" ) { + func = dataTypeExpression; + dataTypeExpression = "*"; + } + + var dataType, + i = 0, + dataTypes = dataTypeExpression.toLowerCase().match( rnothtmlwhite ) || []; + + if ( isFunction( func ) ) { + + // For each dataType in the dataTypeExpression + while ( ( dataType = dataTypes[ i++ ] ) ) { + + // Prepend if requested + if ( dataType[ 0 ] === "+" ) { + dataType = dataType.slice( 1 ) || "*"; + ( structure[ dataType ] = structure[ dataType ] || [] ).unshift( func ); + + // Otherwise append + } else { + ( structure[ dataType ] = structure[ dataType ] || [] ).push( func ); + } + } + } + }; +} + +// Base inspection function for prefilters and transports +function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) { + + var inspected = {}, + seekingTransport = ( structure === transports ); + + function inspect( dataType ) { + var selected; + inspected[ dataType ] = true; + jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) { + var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR ); + if ( typeof dataTypeOrTransport === "string" && + !seekingTransport && !inspected[ dataTypeOrTransport ] ) { + + options.dataTypes.unshift( dataTypeOrTransport ); + inspect( dataTypeOrTransport ); + return false; + } else if ( seekingTransport ) { + return !( selected = dataTypeOrTransport ); + } + } ); + return selected; + } + + return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" ); +} + +// A special extend for ajax options +// that takes "flat" options (not to be deep extended) +// Fixes #9887 +function ajaxExtend( target, src ) { + var key, deep, + flatOptions = jQuery.ajaxSettings.flatOptions || {}; + + for ( key in src ) { + if ( src[ key ] !== undefined ) { + ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ]; + } + } + if ( deep ) { + jQuery.extend( true, target, deep ); + } + + return target; +} + +/* Handles responses to an ajax request: + * - finds the right dataType (mediates between content-type and expected dataType) + * - returns the corresponding response + */ +function ajaxHandleResponses( s, jqXHR, responses ) { + + var ct, type, finalDataType, firstDataType, + contents = s.contents, + dataTypes = s.dataTypes; + + // Remove auto dataType and get content-type in the process + while ( dataTypes[ 0 ] === "*" ) { + dataTypes.shift(); + if ( ct === undefined ) { + ct = s.mimeType || jqXHR.getResponseHeader( "Content-Type" ); + } + } + + // Check if we're dealing with a known content-type + if ( ct ) { + for ( type in contents ) { + if ( contents[ type ] && contents[ type ].test( ct ) ) { + dataTypes.unshift( type ); + break; + } + } + } + + // Check to see if we have a response for the expected dataType + if ( dataTypes[ 0 ] in responses ) { + finalDataType = dataTypes[ 0 ]; + } else { + + // Try convertible dataTypes + for ( type in responses ) { + if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[ 0 ] ] ) { + finalDataType = type; + break; + } + if ( !firstDataType ) { + firstDataType = type; + } + } + + // Or just use first one + finalDataType = finalDataType || firstDataType; + } + + // If we found a dataType + // We add the dataType to the list if needed + // and return the corresponding response + if ( finalDataType ) { + if ( finalDataType !== dataTypes[ 0 ] ) { + dataTypes.unshift( finalDataType ); + } + return responses[ finalDataType ]; + } +} + +/* Chain conversions given the request and the original response + * Also sets the responseXXX fields on the jqXHR instance + */ +function ajaxConvert( s, response, jqXHR, isSuccess ) { + var conv2, current, conv, tmp, prev, + converters = {}, + + // Work with a copy of dataTypes in case we need to modify it for conversion + dataTypes = s.dataTypes.slice(); + + // Create converters map with lowercased keys + if ( dataTypes[ 1 ] ) { + for ( conv in s.converters ) { + converters[ conv.toLowerCase() ] = s.converters[ conv ]; + } + } + + current = dataTypes.shift(); + + // Convert to each sequential dataType + while ( current ) { + + if ( s.responseFields[ current ] ) { + jqXHR[ s.responseFields[ current ] ] = response; + } + + // Apply the dataFilter if provided + if ( !prev && isSuccess && s.dataFilter ) { + response = s.dataFilter( response, s.dataType ); + } + + prev = current; + current = dataTypes.shift(); + + if ( current ) { + + // There's only work to do if current dataType is non-auto + if ( current === "*" ) { + + current = prev; + + // Convert response if prev dataType is non-auto and differs from current + } else if ( prev !== "*" && prev !== current ) { + + // Seek a direct converter + conv = converters[ prev + " " + current ] || converters[ "* " + current ]; + + // If none found, seek a pair + if ( !conv ) { + for ( conv2 in converters ) { + + // If conv2 outputs current + tmp = conv2.split( " " ); + if ( tmp[ 1 ] === current ) { + + // If prev can be converted to accepted input + conv = converters[ prev + " " + tmp[ 0 ] ] || + converters[ "* " + tmp[ 0 ] ]; + if ( conv ) { + + // Condense equivalence converters + if ( conv === true ) { + conv = converters[ conv2 ]; + + // Otherwise, insert the intermediate dataType + } else if ( converters[ conv2 ] !== true ) { + current = tmp[ 0 ]; + dataTypes.unshift( tmp[ 1 ] ); + } + break; + } + } + } + } + + // Apply converter (if not an equivalence) + if ( conv !== true ) { + + // Unless errors are allowed to bubble, catch and return them + if ( conv && s.throws ) { + response = conv( response ); + } else { + try { + response = conv( response ); + } catch ( e ) { + return { + state: "parsererror", + error: conv ? e : "No conversion from " + prev + " to " + current + }; + } + } + } + } + } + } + + return { state: "success", data: response }; +} + +jQuery.extend( { + + // Counter for holding the number of active queries + active: 0, + + // Last-Modified header cache for next request + lastModified: {}, + etag: {}, + + ajaxSettings: { + url: location.href, + type: "GET", + isLocal: rlocalProtocol.test( location.protocol ), + global: true, + processData: true, + async: true, + contentType: "application/x-www-form-urlencoded; charset=UTF-8", + + /* + timeout: 0, + data: null, + dataType: null, + username: null, + password: null, + cache: null, + throws: false, + traditional: false, + headers: {}, + */ + + accepts: { + "*": allTypes, + text: "text/plain", + html: "text/html", + xml: "application/xml, text/xml", + json: "application/json, text/javascript" + }, + + contents: { + xml: /\bxml\b/, + html: /\bhtml/, + json: /\bjson\b/ + }, + + responseFields: { + xml: "responseXML", + text: "responseText", + json: "responseJSON" + }, + + // Data converters + // Keys separate source (or catchall "*") and destination types with a single space + converters: { + + // Convert anything to text + "* text": String, + + // Text to html (true = no transformation) + "text html": true, + + // Evaluate text as a json expression + "text json": JSON.parse, + + // Parse text as xml + "text xml": jQuery.parseXML + }, + + // For options that shouldn't be deep extended: + // you can add your own custom options here if + // and when you create one that shouldn't be + // deep extended (see ajaxExtend) + flatOptions: { + url: true, + context: true + } + }, + + // Creates a full fledged settings object into target + // with both ajaxSettings and settings fields. + // If target is omitted, writes into ajaxSettings. + ajaxSetup: function( target, settings ) { + return settings ? + + // Building a settings object + ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) : + + // Extending ajaxSettings + ajaxExtend( jQuery.ajaxSettings, target ); + }, + + ajaxPrefilter: addToPrefiltersOrTransports( prefilters ), + ajaxTransport: addToPrefiltersOrTransports( transports ), + + // Main method + ajax: function( url, options ) { + + // If url is an object, simulate pre-1.5 signature + if ( typeof url === "object" ) { + options = url; + url = undefined; + } + + // Force options to be an object + options = options || {}; + + var transport, + + // URL without anti-cache param + cacheURL, + + // Response headers + responseHeadersString, + responseHeaders, + + // timeout handle + timeoutTimer, + + // Url cleanup var + urlAnchor, + + // Request state (becomes false upon send and true upon completion) + completed, + + // To know if global events are to be dispatched + fireGlobals, + + // Loop variable + i, + + // uncached part of the url + uncached, + + // Create the final options object + s = jQuery.ajaxSetup( {}, options ), + + // Callbacks context + callbackContext = s.context || s, + + // Context for global events is callbackContext if it is a DOM node or jQuery collection + globalEventContext = s.context && + ( callbackContext.nodeType || callbackContext.jquery ) ? + jQuery( callbackContext ) : + jQuery.event, + + // Deferreds + deferred = jQuery.Deferred(), + completeDeferred = jQuery.Callbacks( "once memory" ), + + // Status-dependent callbacks + statusCode = s.statusCode || {}, + + // Headers (they are sent all at once) + requestHeaders = {}, + requestHeadersNames = {}, + + // Default abort message + strAbort = "canceled", + + // Fake xhr + jqXHR = { + readyState: 0, + + // Builds headers hashtable if needed + getResponseHeader: function( key ) { + var match; + if ( completed ) { + if ( !responseHeaders ) { + responseHeaders = {}; + while ( ( match = rheaders.exec( responseHeadersString ) ) ) { + responseHeaders[ match[ 1 ].toLowerCase() + " " ] = + ( responseHeaders[ match[ 1 ].toLowerCase() + " " ] || [] ) + .concat( match[ 2 ] ); + } + } + match = responseHeaders[ key.toLowerCase() + " " ]; + } + return match == null ? null : match.join( ", " ); + }, + + // Raw string + getAllResponseHeaders: function() { + return completed ? responseHeadersString : null; + }, + + // Caches the header + setRequestHeader: function( name, value ) { + if ( completed == null ) { + name = requestHeadersNames[ name.toLowerCase() ] = + requestHeadersNames[ name.toLowerCase() ] || name; + requestHeaders[ name ] = value; + } + return this; + }, + + // Overrides response content-type header + overrideMimeType: function( type ) { + if ( completed == null ) { + s.mimeType = type; + } + return this; + }, + + // Status-dependent callbacks + statusCode: function( map ) { + var code; + if ( map ) { + if ( completed ) { + + // Execute the appropriate callbacks + jqXHR.always( map[ jqXHR.status ] ); + } else { + + // Lazy-add the new callbacks in a way that preserves old ones + for ( code in map ) { + statusCode[ code ] = [ statusCode[ code ], map[ code ] ]; + } + } + } + return this; + }, + + // Cancel the request + abort: function( statusText ) { + var finalText = statusText || strAbort; + if ( transport ) { + transport.abort( finalText ); + } + done( 0, finalText ); + return this; + } + }; + + // Attach deferreds + deferred.promise( jqXHR ); + + // Add protocol if not provided (prefilters might expect it) + // Handle falsy url in the settings object (#10093: consistency with old signature) + // We also use the url parameter if available + s.url = ( ( url || s.url || location.href ) + "" ) + .replace( rprotocol, location.protocol + "//" ); + + // Alias method option to type as per ticket #12004 + s.type = options.method || options.type || s.method || s.type; + + // Extract dataTypes list + s.dataTypes = ( s.dataType || "*" ).toLowerCase().match( rnothtmlwhite ) || [ "" ]; + + // A cross-domain request is in order when the origin doesn't match the current origin. + if ( s.crossDomain == null ) { + urlAnchor = document.createElement( "a" ); + + // Support: IE <=8 - 11, Edge 12 - 15 + // IE throws exception on accessing the href property if url is malformed, + // e.g. http://example.com:80x/ + try { + urlAnchor.href = s.url; + + // Support: IE <=8 - 11 only + // Anchor's host property isn't correctly set when s.url is relative + urlAnchor.href = urlAnchor.href; + s.crossDomain = originAnchor.protocol + "//" + originAnchor.host !== + urlAnchor.protocol + "//" + urlAnchor.host; + } catch ( e ) { + + // If there is an error parsing the URL, assume it is crossDomain, + // it can be rejected by the transport if it is invalid + s.crossDomain = true; + } + } + + // Convert data if not already a string + if ( s.data && s.processData && typeof s.data !== "string" ) { + s.data = jQuery.param( s.data, s.traditional ); + } + + // Apply prefilters + inspectPrefiltersOrTransports( prefilters, s, options, jqXHR ); + + // If request was aborted inside a prefilter, stop there + if ( completed ) { + return jqXHR; + } + + // We can fire global events as of now if asked to + // Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118) + fireGlobals = jQuery.event && s.global; + + // Watch for a new set of requests + if ( fireGlobals && jQuery.active++ === 0 ) { + jQuery.event.trigger( "ajaxStart" ); + } + + // Uppercase the type + s.type = s.type.toUpperCase(); + + // Determine if request has content + s.hasContent = !rnoContent.test( s.type ); + + // Save the URL in case we're toying with the If-Modified-Since + // and/or If-None-Match header later on + // Remove hash to simplify url manipulation + cacheURL = s.url.replace( rhash, "" ); + + // More options handling for requests with no content + if ( !s.hasContent ) { + + // Remember the hash so we can put it back + uncached = s.url.slice( cacheURL.length ); + + // If data is available and should be processed, append data to url + if ( s.data && ( s.processData || typeof s.data === "string" ) ) { + cacheURL += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data; + + // #9682: remove data so that it's not used in an eventual retry + delete s.data; + } + + // Add or update anti-cache param if needed + if ( s.cache === false ) { + cacheURL = cacheURL.replace( rantiCache, "$1" ); + uncached = ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ( nonce.guid++ ) + + uncached; + } + + // Put hash and anti-cache on the URL that will be requested (gh-1732) + s.url = cacheURL + uncached; + + // Change '%20' to '+' if this is encoded form body content (gh-2658) + } else if ( s.data && s.processData && + ( s.contentType || "" ).indexOf( "application/x-www-form-urlencoded" ) === 0 ) { + s.data = s.data.replace( r20, "+" ); + } + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + if ( jQuery.lastModified[ cacheURL ] ) { + jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] ); + } + if ( jQuery.etag[ cacheURL ] ) { + jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] ); + } + } + + // Set the correct header, if data is being sent + if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) { + jqXHR.setRequestHeader( "Content-Type", s.contentType ); + } + + // Set the Accepts header for the server, depending on the dataType + jqXHR.setRequestHeader( + "Accept", + s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ? + s.accepts[ s.dataTypes[ 0 ] ] + + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) : + s.accepts[ "*" ] + ); + + // Check for headers option + for ( i in s.headers ) { + jqXHR.setRequestHeader( i, s.headers[ i ] ); + } + + // Allow custom headers/mimetypes and early abort + if ( s.beforeSend && + ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || completed ) ) { + + // Abort if not done already and return + return jqXHR.abort(); + } + + // Aborting is no longer a cancellation + strAbort = "abort"; + + // Install callbacks on deferreds + completeDeferred.add( s.complete ); + jqXHR.done( s.success ); + jqXHR.fail( s.error ); + + // Get transport + transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR ); + + // If no transport, we auto-abort + if ( !transport ) { + done( -1, "No Transport" ); + } else { + jqXHR.readyState = 1; + + // Send global event + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] ); + } + + // If request was aborted inside ajaxSend, stop there + if ( completed ) { + return jqXHR; + } + + // Timeout + if ( s.async && s.timeout > 0 ) { + timeoutTimer = window.setTimeout( function() { + jqXHR.abort( "timeout" ); + }, s.timeout ); + } + + try { + completed = false; + transport.send( requestHeaders, done ); + } catch ( e ) { + + // Rethrow post-completion exceptions + if ( completed ) { + throw e; + } + + // Propagate others as results + done( -1, e ); + } + } + + // Callback for when everything is done + function done( status, nativeStatusText, responses, headers ) { + var isSuccess, success, error, response, modified, + statusText = nativeStatusText; + + // Ignore repeat invocations + if ( completed ) { + return; + } + + completed = true; + + // Clear timeout if it exists + if ( timeoutTimer ) { + window.clearTimeout( timeoutTimer ); + } + + // Dereference transport for early garbage collection + // (no matter how long the jqXHR object will be used) + transport = undefined; + + // Cache response headers + responseHeadersString = headers || ""; + + // Set readyState + jqXHR.readyState = status > 0 ? 4 : 0; + + // Determine if successful + isSuccess = status >= 200 && status < 300 || status === 304; + + // Get response data + if ( responses ) { + response = ajaxHandleResponses( s, jqXHR, responses ); + } + + // Use a noop converter for missing script but not if jsonp + if ( !isSuccess && + jQuery.inArray( "script", s.dataTypes ) > -1 && + jQuery.inArray( "json", s.dataTypes ) < 0 ) { + s.converters[ "text script" ] = function() {}; + } + + // Convert no matter what (that way responseXXX fields are always set) + response = ajaxConvert( s, response, jqXHR, isSuccess ); + + // If successful, handle type chaining + if ( isSuccess ) { + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + modified = jqXHR.getResponseHeader( "Last-Modified" ); + if ( modified ) { + jQuery.lastModified[ cacheURL ] = modified; + } + modified = jqXHR.getResponseHeader( "etag" ); + if ( modified ) { + jQuery.etag[ cacheURL ] = modified; + } + } + + // if no content + if ( status === 204 || s.type === "HEAD" ) { + statusText = "nocontent"; + + // if not modified + } else if ( status === 304 ) { + statusText = "notmodified"; + + // If we have data, let's convert it + } else { + statusText = response.state; + success = response.data; + error = response.error; + isSuccess = !error; + } + } else { + + // Extract error from statusText and normalize for non-aborts + error = statusText; + if ( status || !statusText ) { + statusText = "error"; + if ( status < 0 ) { + status = 0; + } + } + } + + // Set data for the fake xhr object + jqXHR.status = status; + jqXHR.statusText = ( nativeStatusText || statusText ) + ""; + + // Success/Error + if ( isSuccess ) { + deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] ); + } else { + deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] ); + } + + // Status-dependent callbacks + jqXHR.statusCode( statusCode ); + statusCode = undefined; + + if ( fireGlobals ) { + globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError", + [ jqXHR, s, isSuccess ? success : error ] ); + } + + // Complete + completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] ); + + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] ); + + // Handle the global AJAX counter + if ( !( --jQuery.active ) ) { + jQuery.event.trigger( "ajaxStop" ); + } + } + } + + return jqXHR; + }, + + getJSON: function( url, data, callback ) { + return jQuery.get( url, data, callback, "json" ); + }, + + getScript: function( url, callback ) { + return jQuery.get( url, undefined, callback, "script" ); + } +} ); + +jQuery.each( [ "get", "post" ], function( _i, method ) { + jQuery[ method ] = function( url, data, callback, type ) { + + // Shift arguments if data argument was omitted + if ( isFunction( data ) ) { + type = type || callback; + callback = data; + data = undefined; + } + + // The url can be an options object (which then must have .url) + return jQuery.ajax( jQuery.extend( { + url: url, + type: method, + dataType: type, + data: data, + success: callback + }, jQuery.isPlainObject( url ) && url ) ); + }; +} ); + +jQuery.ajaxPrefilter( function( s ) { + var i; + for ( i in s.headers ) { + if ( i.toLowerCase() === "content-type" ) { + s.contentType = s.headers[ i ] || ""; + } + } +} ); + + +jQuery._evalUrl = function( url, options, doc ) { + return jQuery.ajax( { + url: url, + + // Make this explicit, since user can override this through ajaxSetup (#11264) + type: "GET", + dataType: "script", + cache: true, + async: false, + global: false, + + // Only evaluate the response if it is successful (gh-4126) + // dataFilter is not invoked for failure responses, so using it instead + // of the default converter is kludgy but it works. + converters: { + "text script": function() {} + }, + dataFilter: function( response ) { + jQuery.globalEval( response, options, doc ); + } + } ); +}; + + +jQuery.fn.extend( { + wrapAll: function( html ) { + var wrap; + + if ( this[ 0 ] ) { + if ( isFunction( html ) ) { + html = html.call( this[ 0 ] ); + } + + // The elements to wrap the target around + wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true ); + + if ( this[ 0 ].parentNode ) { + wrap.insertBefore( this[ 0 ] ); + } + + wrap.map( function() { + var elem = this; + + while ( elem.firstElementChild ) { + elem = elem.firstElementChild; + } + + return elem; + } ).append( this ); + } + + return this; + }, + + wrapInner: function( html ) { + if ( isFunction( html ) ) { + return this.each( function( i ) { + jQuery( this ).wrapInner( html.call( this, i ) ); + } ); + } + + return this.each( function() { + var self = jQuery( this ), + contents = self.contents(); + + if ( contents.length ) { + contents.wrapAll( html ); + + } else { + self.append( html ); + } + } ); + }, + + wrap: function( html ) { + var htmlIsFunction = isFunction( html ); + + return this.each( function( i ) { + jQuery( this ).wrapAll( htmlIsFunction ? html.call( this, i ) : html ); + } ); + }, + + unwrap: function( selector ) { + this.parent( selector ).not( "body" ).each( function() { + jQuery( this ).replaceWith( this.childNodes ); + } ); + return this; + } +} ); + + +jQuery.expr.pseudos.hidden = function( elem ) { + return !jQuery.expr.pseudos.visible( elem ); +}; +jQuery.expr.pseudos.visible = function( elem ) { + return !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length ); +}; + + + + +jQuery.ajaxSettings.xhr = function() { + try { + return new window.XMLHttpRequest(); + } catch ( e ) {} +}; + +var xhrSuccessStatus = { + + // File protocol always yields status code 0, assume 200 + 0: 200, + + // Support: IE <=9 only + // #1450: sometimes IE returns 1223 when it should be 204 + 1223: 204 + }, + xhrSupported = jQuery.ajaxSettings.xhr(); + +support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported ); +support.ajax = xhrSupported = !!xhrSupported; + +jQuery.ajaxTransport( function( options ) { + var callback, errorCallback; + + // Cross domain only allowed if supported through XMLHttpRequest + if ( support.cors || xhrSupported && !options.crossDomain ) { + return { + send: function( headers, complete ) { + var i, + xhr = options.xhr(); + + xhr.open( + options.type, + options.url, + options.async, + options.username, + options.password + ); + + // Apply custom fields if provided + if ( options.xhrFields ) { + for ( i in options.xhrFields ) { + xhr[ i ] = options.xhrFields[ i ]; + } + } + + // Override mime type if needed + if ( options.mimeType && xhr.overrideMimeType ) { + xhr.overrideMimeType( options.mimeType ); + } + + // X-Requested-With header + // For cross-domain requests, seeing as conditions for a preflight are + // akin to a jigsaw puzzle, we simply never set it to be sure. + // (it can always be set on a per-request basis or even using ajaxSetup) + // For same-domain requests, won't change header if already provided. + if ( !options.crossDomain && !headers[ "X-Requested-With" ] ) { + headers[ "X-Requested-With" ] = "XMLHttpRequest"; + } + + // Set headers + for ( i in headers ) { + xhr.setRequestHeader( i, headers[ i ] ); + } + + // Callback + callback = function( type ) { + return function() { + if ( callback ) { + callback = errorCallback = xhr.onload = + xhr.onerror = xhr.onabort = xhr.ontimeout = + xhr.onreadystatechange = null; + + if ( type === "abort" ) { + xhr.abort(); + } else if ( type === "error" ) { + + // Support: IE <=9 only + // On a manual native abort, IE9 throws + // errors on any property access that is not readyState + if ( typeof xhr.status !== "number" ) { + complete( 0, "error" ); + } else { + complete( + + // File: protocol always yields status 0; see #8605, #14207 + xhr.status, + xhr.statusText + ); + } + } else { + complete( + xhrSuccessStatus[ xhr.status ] || xhr.status, + xhr.statusText, + + // Support: IE <=9 only + // IE9 has no XHR2 but throws on binary (trac-11426) + // For XHR2 non-text, let the caller handle it (gh-2498) + ( xhr.responseType || "text" ) !== "text" || + typeof xhr.responseText !== "string" ? + { binary: xhr.response } : + { text: xhr.responseText }, + xhr.getAllResponseHeaders() + ); + } + } + }; + }; + + // Listen to events + xhr.onload = callback(); + errorCallback = xhr.onerror = xhr.ontimeout = callback( "error" ); + + // Support: IE 9 only + // Use onreadystatechange to replace onabort + // to handle uncaught aborts + if ( xhr.onabort !== undefined ) { + xhr.onabort = errorCallback; + } else { + xhr.onreadystatechange = function() { + + // Check readyState before timeout as it changes + if ( xhr.readyState === 4 ) { + + // Allow onerror to be called first, + // but that will not handle a native abort + // Also, save errorCallback to a variable + // as xhr.onerror cannot be accessed + window.setTimeout( function() { + if ( callback ) { + errorCallback(); + } + } ); + } + }; + } + + // Create the abort callback + callback = callback( "abort" ); + + try { + + // Do send the request (this may raise an exception) + xhr.send( options.hasContent && options.data || null ); + } catch ( e ) { + + // #14683: Only rethrow if this hasn't been notified as an error yet + if ( callback ) { + throw e; + } + } + }, + + abort: function() { + if ( callback ) { + callback(); + } + } + }; + } +} ); + + + + +// Prevent auto-execution of scripts when no explicit dataType was provided (See gh-2432) +jQuery.ajaxPrefilter( function( s ) { + if ( s.crossDomain ) { + s.contents.script = false; + } +} ); + +// Install script dataType +jQuery.ajaxSetup( { + accepts: { + script: "text/javascript, application/javascript, " + + "application/ecmascript, application/x-ecmascript" + }, + contents: { + script: /\b(?:java|ecma)script\b/ + }, + converters: { + "text script": function( text ) { + jQuery.globalEval( text ); + return text; + } + } +} ); + +// Handle cache's special case and crossDomain +jQuery.ajaxPrefilter( "script", function( s ) { + if ( s.cache === undefined ) { + s.cache = false; + } + if ( s.crossDomain ) { + s.type = "GET"; + } +} ); + +// Bind script tag hack transport +jQuery.ajaxTransport( "script", function( s ) { + + // This transport only deals with cross domain or forced-by-attrs requests + if ( s.crossDomain || s.scriptAttrs ) { + var script, callback; + return { + send: function( _, complete ) { + script = jQuery( " + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    + +
    +
    +
    +
    + +
    +

    4. Background

    +
    +

    4.1. Code Overview

    +

    We present an automated route-planning method for use by an ice-strengthened vessel operating in polar regions. We build on the method developed for underwater vehicle long-distance route planning reported in Fox et al (2021). We start with the same grid-based route construction approach to obtain routes that satisfy constraints on the performance of the ship in ice. We then apply a novel route-smoothing method to the resulting routes, shortening the grid-based routes and ensure that routes follow great circle arcs where possible. This two-stage process efficiently generates routes that follow standard navigation solutions in open water and optimise vessel performance in and around areas dominated by sea ice. While we have focussed on navigation in and around polar ice, our methods are also applicable to shipping in a broader context (e.g.: commercial shipping) where route-planning must be responsive to changing local and weather conditions.

    +
    +
    +

    4.2. Code Structure

    +

    The outline of this manual is to provide the user with all the tools that they need to run the software for a set of examples. We also hope that the background information supplied for each section allows the user to understand the methods used throughout this toolkit.

    +

    The separate stages of the codebase can be broken down into:

    +
      +
    1. Dataloaders - Reading in different datasets of differing types. Throughout this section we will outline the form that the input datasets should take and useful tips for pre-processing your data.

    2. +
    3. Mesh Construction - Generating a Digital Twin of the environmental conditions. In this section we outline the different Python classes that are used to construct a discretised representation across the user defined datasets, giving a coding background to the dynamic splitting of the mesh to finer resolution in regions of datasets that are spatially varying.

    4. +
    +

    Each stage of this pipeline makes use of a configuration file, found in the Configuration Overview section of the documentation +and produces an output file, the form of which can be found in the Outputs - Data Types section of this document.

    +

    In addition to the main section of the codebase we have also developed a series of plotting classes that allows the user to generate interactive maps and static figures for the Mesh Features. These can be found in the Plotting section later in the manual.

    +
    +
    + + +
    +
    + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/docs/html/sections/Command_line_interface.html b/docs/html/sections/Command_line_interface.html new file mode 100644 index 00000000..fcf1a009 --- /dev/null +++ b/docs/html/sections/Command_line_interface.html @@ -0,0 +1,235 @@ + + + + + + + 3. Command Line Interface — meshiphi 1.1.5 documentation + + + + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    + +
    +
    +
    +
    + +
    +

    3. Command Line Interface

    +

    The MeshiPhi package provides CLI entry points, used to build a digital environment from a hetrogeneous collection of source data. +This digital environment file (mesh) may then be exported to a variety of file formats for use in other systems, such as GIS software. +The produced mesh file also interfaces directly with PolarRoute, BAS’s route planning software to provide optinal routes through mesh.

    +
    +

    3.1. create_mesh

    +

    The create_mesh entry point builds a digital environment file from a collection of source data, which can then be used +by the vessel performance modeller and route planner.

    +
    create_mesh <config.json>
    +
    +
    +

    positional arguments:

    +
    config : A configuration file detailing how to build the digital environment. JSON parsable
    +
    +
    +

    The format of the required <config.json> file can be found in the Configuration - Mesh Construction section of the documentation. +There are also example configuration files available in the directory examples/environment_config/grf_example.config.json

    +

    optional arguments:

    +
    -v (verbose logging)
    +-o <output location> (set output location for mesh)
    +
    +
    +

    The format of the returned mesh.json file is explain in The Mesh.json file section of the documentation.

    +
    +
    +

    3.2. export_mesh

    +

    Once a mesh has been built using the create_mesh command, it can be exported other file types for +use in other systems (such as GIS software) using the the export_mesh command.

    +
    export_mesh <mesh.json> <output_location> <output_format>
    +
    +
    +

    positional arguments:

    +
    mesh : A digital environment file.
    +output_location : The location to save the exported mesh.
    +output_format : The format to export the mesh to.
    +
    +
    +
    +
    supported output formats are:
      +
    • .json (default) [JSON]

    • +
    • geo.json (collection of polygons for each cell in the mesh) [GEOJSON]

    • +
    • .tif (rasterised mesh) [TIF]

    • +
    • .png [PNG]

    • +
    +
    +
    +

    optional arguments:

    +
    -v : verbose logging
    +-o : output location
    +-format_conf: configuration file for output format (required for TIF export, optional for GEOJSON)
    +
    +
    +

    the format of the <format_conf.json> file required for .tif export is as follows:

    +
    {
    +    "data_name": "elevation",
    +    "sampling_resolution": [
    +        150,
    +        150
    +    ],
    +    "projection": "3031",
    +    "color_conf": "path to/color_conf.txt"
    +}
    +
    +
    +
    +
    where the variables are as follows:
      +
    • data_name : The name of the data to be exported. This is the name of the data layer in the mesh.

    • +
    • sampling_resolution : The resolution of the exported mesh. This is a list of two values, the first being the x resolution and the second being the y resolution.

    • +
    • projection : The projection of the exported mesh. This is a string of the EPSG code of the projection.

    • +
    • color_conf : The path to the color configuration file. This is a text file containing the color scheme to be used when exporting the mesh. The format of this file is as follows:

    • +
    +
    +
    +
    0 240 250 160
    +30 230 220 170
    +60 220 220 220
    +100 250 250 250
    +
    +
    +

    The color_conf.txt contains 4 columns per line: the data_name value and the +corresponding red, green, blue value between 0 and 255.

    +

    When using the -format_conf option for GEOJSON output the only variable required is the data_name. This specifies which of the data layers you want to export as a single GEOJSON file.

    +
    +
    +

    3.3. rebuild_mesh

    +

    Once a mesh has been built using the create_mesh command the rebuild_mesh command allows a user to rebuild it based on the +original configs stored within the mesh file. This is primarily useful for debugging or to update old meshes produced with an older version +of the package. Running this command will also reapply any vessel performance simulations, if these were run on the original mesh.

    +
    rebuild_mesh <mesh.json>
    +
    +
    +

    optional arguments:

    +
    -v : verbose logging
    +-o : output location
    +
    +
    +
    +
    +

    3.4. plot_mesh (GeoPlot)

    +

    Meshes produced at any stage in the route planning process can be visualised using the GeoPlot +library found at the relevant GitHub page. Meshes and routes can also be +plotted in other GIS software such as QGIS by exporting the mesh to a common format such as .geojson or .tif using +the export_mesh command.

    +
    plot_mesh <mesh.json>
    +
    +
    +

    optional arguments:

    +
    -v : verbose logging
    +-o : output location
    +
    +
    +
    +
    + + +
    +
    + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/docs/html/sections/Configuration/Configuration_overview.html b/docs/html/sections/Configuration/Configuration_overview.html new file mode 100644 index 00000000..7388273b --- /dev/null +++ b/docs/html/sections/Configuration/Configuration_overview.html @@ -0,0 +1,243 @@ + + + + + + + 5. Configuration Overview — meshiphi 1.1.5 documentation + + + + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    + +
    +
    +
    +
    + +
    +

    5. Configuration Overview

    +

    In this section we will outline the standard structure for a configuration file used in +all portions of the PolarRoute software package.

    +

    Each stage of the route-planning process is configured by a separate configuration file. +The configuration files are written in JSON, and are passed to each stage of the +route-planning process as command-line arguments or through a Python script.

    +

    Example configuration files are provided in the config directory.

    +

    Descriptions of the configuration options for the Mesh Construction can be found in +the Configuration - Mesh Construction section of the documentation.

    + +
    +

    5.2. Config Validation

    +

    At each major stage of the code (mesh construction, vessel performance modelling, +and route planning), the configs supplied are validated using a template JSON Schema. +These schema check that the correct keywords and datatypes are provided in the config +JSON’s, as well as the waypoints CSV file. They also perform rudimentary checks on the +values to ensure that they make sense (e.g. startTime is before endTime).

    +
    +
    +meshiphi.config_validation.config_validator.flexi_json_input(config)
    +

    Allows flexible inputs. If a string is parsed, then assume it’s a file path +and read in as a json. If a dict is parsed, then assume it’s already a +valid loaded json, and return it as is

    +
    +
    Parameters:
    +

    config (str or dict) – Input to translate into a dict.

    +
    +
    Raises:
    +

    TypeError – If input is neither a str nor a dict, then wrong input type

    +
    +
    Returns:
    +

    Dictionary read from JSON

    +
    +
    Return type:
    +

    dict

    +
    +
    +
    + +
    +
    +meshiphi.config_validation.config_validator.validate_mesh_config(config)
    +

    Validates a mesh config

    +
    +
    Parameters:
    +

    config (str or dict) – Mesh config to be validated. +If type ‘str’, tries to read in as a filename and open file as json +If type ‘dict’, assumes it’s already read in from a json file

    +
    +
    Raises:
    +
      +
    • TypeError – Incorrect config parsed in. Must be ‘str’ or ‘dict’

    • +
    • FileNotFoundError – Could not read in file if ‘str’ parsed

    • +
    • ValidationError – Malformed mesh config

    • +
    +
    +
    +
    + +
    +
    +meshiphi.config_validation.config_validator.validate_route_config(config)
    +

    Validates a route config

    +
    +
    Parameters:
    +

    config (str or dict) – route config to be validated. +If type ‘str’, tries to read in as a filename and open file as json +If type ‘dict’, assumes it’s already read in from a json file

    +
    +
    Raises:
    +
      +
    • TypeError – Incorrect config parsed in. Must be ‘str’ or ‘dict’

    • +
    • FileNotFoundError – Could not read in file if ‘str’ parsed

    • +
    • ValidationError – Malformed route config

    • +
    +
    +
    +
    + +
    +
    +meshiphi.config_validation.config_validator.validate_vessel_config(config)
    +

    Validates a vessel config

    +
    +
    Parameters:
    +

    config (str or dict) – Vessel config to be validated. +If type ‘str’, tries to read in as a filename and open file as json +If type ‘dict’, assumes it’s already read in from a json file

    +
    +
    Raises:
    +
      +
    • TypeError – Incorrect config parsed in. Must be ‘str’ or ‘dict’

    • +
    • FileNotFoundError – Could not read in file if ‘str’ parsed

    • +
    • ValidationError – Malformed vessel config

    • +
    +
    +
    +
    + +
    +
    +meshiphi.config_validation.config_validator.validate_waypoints(waypoints)
    +

    _summary_

    +
    +
    Parameters:
    +

    waypoints (str or pd.DataFrame) – _description_

    +
    +
    Raises:
    +
      +
    • TypeError – Incorrect config parsed in. Must be ‘str’ or ‘pd.DataFrame’

    • +
    • FileNotFoundError – Could not read in file if ‘str’ parsed

    • +
    • AssertionError – Malformed waypoints config

    • +
    +
    +
    +
    + +
    +
    + + +
    +
    + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/docs/html/sections/Configuration/Mesh_construction_config.html b/docs/html/sections/Configuration/Mesh_construction_config.html new file mode 100644 index 00000000..240deabe --- /dev/null +++ b/docs/html/sections/Configuration/Mesh_construction_config.html @@ -0,0 +1,519 @@ + + + + + + + 5.1. Configuration - Mesh Construction — meshiphi 1.1.5 documentation + + + + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    + +
    +
    +
    +
    + +
    +

    5.1. Configuration - Mesh Construction

    +

    Below is a full configuration file for building an environmental mesh using +data generated from gaussian random fields. This configuration file generates +the feilds ‘SIC’, ‘elevation’, ‘thickness’, ‘density’, ‘uC,vC’ (currents) and +‘u10,v10’ (winds). The full configuration file is available in the file location +examples/environment_config/grf_example.config.json. Other example +configuration files are also available at this location, including configuration files +which build meshes using real data-sets.

    +
    {
    +    "region": {
    +        "lat_min": 0,
    +        "lat_max": 10,
    +        "long_min": 0,
    +        "long_max": 10,
    +        "start_time": "2017-02-01",
    +        "end_time": "2017-02-04",
    +        "cell_width": 10,
    +        "cell_height": 10
    +    },
    +    "data_sources": [
    +        {
    +            "loader": "scalar_grf",
    +            "params": {
    +                "data_name": "SIC",
    +                "min": 0,
    +                "max": 100,
    +                "seed": 16,
    +                "offset": 5,
    +                "splitting_conditions": [
    +                    {
    +                        "SIC": {
    +                            "threshold": 75,
    +                            "upper_bound": 1.0,
    +                            "lower_bound": 0.0
    +                        }
    +                    }
    +                ],
    +                "dataloader_name": "scalar_grf",
    +                "downsample_factors": [
    +                    1,
    +                    1
    +                ],
    +                "aggregate_type": "MEAN",
    +                "min_dp": 5,
    +                "in_proj": "EPSG:4326",
    +                "out_proj": "EPSG:4326",
    +                "x_col": "lat",
    +                "y_col": "long",
    +                "size": 512,
    +                "alpha": 3,
    +                "binary": false,
    +                "threshold": [
    +                    0,
    +                    1
    +                ],
    +                "multiplier": 1
    +            }
    +        },
    +        {
    +            "loader": "scalar_grf",
    +            "params": {
    +                "data_name": "elevation",
    +                "min": -100,
    +                "max": 50,
    +                "seed": 30,
    +                "splitting_conditions": [
    +                    {
    +                        "elevation": {
    +                            "threshold": -10,
    +                            "upper_bound": 1.0,
    +                            "lower_bound": 0.0
    +                        }
    +                    }
    +                ],
    +                "dataloader_name": "scalar_grf",
    +                "downsample_factors": [
    +                    1,
    +                    1
    +                ],
    +                "aggregate_type": "MEAN",
    +                "min_dp": 5,
    +                "in_proj": "EPSG:4326",
    +                "out_proj": "EPSG:4326",
    +                "x_col": "lat",
    +                "y_col": "long",
    +                "size": 512,
    +                "alpha": 3,
    +                "binary": false,
    +                "threshold": [
    +                    0,
    +                    1
    +                ],
    +                "multiplier": 1,
    +                "offset": 0
    +            }
    +        },
    +        {
    +            "loader": "scalar_grf",
    +            "params": {
    +                "data_name": "thickness",
    +                "min": 0.65,
    +                "max": 1.4,
    +                "seed": 44,
    +                "dataloader_name": "scalar_grf",
    +                "downsample_factors": [
    +                    1,
    +                    1
    +                ],
    +                "aggregate_type": "MEAN",
    +                "min_dp": 5,
    +                "in_proj": "EPSG:4326",
    +                "out_proj": "EPSG:4326",
    +                "x_col": "lat",
    +                "y_col": "long",
    +                "size": 512,
    +                "alpha": 3,
    +                "binary": false,
    +                "threshold": [
    +                    0,
    +                    1
    +                ],
    +                "multiplier": 1,
    +                "offset": 0
    +            }
    +        },
    +        {
    +            "loader": "scalar_grf",
    +            "params": {
    +                "data_name": "density",
    +                "min": 850,
    +                "max": 1000,
    +                "seed": 40,
    +                "dataloader_name": "scalar_grf",
    +                "downsample_factors": [
    +                    1,
    +                    1
    +                ],
    +                "aggregate_type": "MEAN",
    +                "min_dp": 5,
    +                "in_proj": "EPSG:4326",
    +                "out_proj": "EPSG:4326",
    +                "x_col": "lat",
    +                "y_col": "long",
    +                "size": 512,
    +                "alpha": 3,
    +                "binary": false,
    +                "threshold": [
    +                    0,
    +                    1
    +                ],
    +                "multiplier": 1,
    +                "offset": 0
    +            }
    +        },
    +        {
    +            "loader": "vector_grf",
    +            "params": {
    +                "data_name": "uC,vC",
    +                "min": 0,
    +                "max": 1,
    +                "seed": 21,
    +                "dataloader_name": "vector_grf",
    +                "downsample_factors": [
    +                    1,
    +                    1
    +                ],
    +                "aggregate_type": "MEAN",
    +                "min_dp": 5,
    +                "in_proj": "EPSG:4326",
    +                "out_proj": "EPSG:4326",
    +                "x_col": "lat",
    +                "y_col": "long",
    +                "size": 512,
    +                "alpha": 3,
    +                "vec_x": "uC",
    +                "vec_y": "vC"
    +            }
    +        },
    +        {
    +            "loader": "vector_grf",
    +            "params": {
    +                "data_name": "u10,v10",
    +                "min": 0,
    +                "max": 1,
    +                "seed": 21,
    +                "dataloader_name": "vector_grf",
    +                "downsample_factors": [
    +                    1,
    +                    1
    +                ],
    +                "aggregate_type": "MEAN",
    +                "min_dp": 5,
    +                "in_proj": "EPSG:4326",
    +                "out_proj": "EPSG:4326",
    +                "x_col": "lat",
    +                "y_col": "long",
    +                "size": 512,
    +                "alpha": 3,
    +                "vec_x": "uC",
    +                "vec_y": "vC"
    +            }
    +        }
    +    ],
    +    "splitting": {
    +        "split_depth": 6,
    +        "minimum_datapoints": 5
    +    }
    +}
    +
    +
    +

    The configuration file used for mesh construction contains information required to build the discretised environment in which the route planner +operates. Information here dictates the region in which the mesh is constructed, the data contained within +the mesh and how the mesh is split to a non-uniform resolution. The configuration file used to generate a mesh is stored in a section titled ‘Mesh_info’

    +

    The ‘Mesh_info’ section of the configuration file contains three primary sections:

    +
    +

    5.1.1. Region

    +

    The region section gives detailed information for the construction of the Discrete Mesh. The main definitions are the bounding region and temporal portion of interest (longMin, latMin, longMax, latMax, startTime, endTime), but also the starting shape of the spatial grid cell boxes (cellWidth, cellHeight) is defined before splitting is applied. Further detail on each parameter is given below:

    +
    "region": {
    +        "lat_min": 0,
    +        "lat_max": 10,
    +        "long_min": 0,
    +        "long_max": 10,
    +        "start_time": "2017-02-01",
    +        "end_time": "2017-02-04",
    +        "cell_width": 10,
    +        "cell_height": 10
    +}
    +
    +
    +

    where the variables are as follows:

    +
      +
    • long_min (float, degrees) : Minimum Longitude Edge Mesh

    • +
    • long_max (float, degrees) : Maximum Longitude Edge Mesh

    • +
    • lat_min (float, degrees) : Minimum Latitude Edge Mesh

    • +
    • lat_max (float, degrees) : Maximum Latitude Edge Mesh

    • +
    • start_time (string, ‘YYYY-mm-dd’) : Start Datetime of Time averaging

    • +
    • end_time (string, ‘YYYY-mm-dd’) : End Datetime of Time averaging

    • +
    • cell_width (float, degrees) : Initial Cell Box Width prior to splitting

    • +
    • cell_height (float, degrees) : Initial Cell Box Height prior to splitting

    • +
    +
    +

    Note

    +

    Variables start_time and end_time also support reference to system time using +the keyword TODAY e.g.

    +

    “startTime”: “TODAY” , “endTime”: “TODAY + 5”

    +

    “startTime”: “TODAY - 3”, “endTime”: “TODAY”

    +
    +
    +
    +

    5.1.2. Data Sources

    +

    The ‘Data Sources’ section of the configuration file dictates which information will be added to the +mesh when constructed. Each item in the list of data sources represents a single data set to be added +to the mesh.

    +
    "data_sources": [
    +     {
    +         "loader": "scalar_grf",
    +         "params": {
    +             "data_name": "SIC",
    +             "min": 0,
    +             "max": 100,
    +             "seed": 16,
    +             "offset": 5,
    +             "splitting_conditions": [
    +                 {
    +                     "SIC": {
    +                         "threshold": 75,
    +                         "upper_bound": 1.0,
    +                         "lower_bound": 0.0
    +                     }
    +                 }
    +             ],
    +             "dataloader_name": "scalar_grf",
    +             "downsample_factors": [
    +                 1,
    +                 1
    +             ],
    +             "aggregate_type": "MEAN",
    +             "min_dp": 5,
    +             "in_proj": "EPSG:4326",
    +             "out_proj": "EPSG:4326",
    +             "x_col": "lat",
    +             "y_col": "long",
    +             "size": 512,
    +             "alpha": 3,
    +             "binary": false,
    +             "threshold": [
    +                 0,
    +                 1
    +             ],
    +             "multiplier": 1
    +         }
    +     },
    +     ... other data_sources
    + ]
    +
    +
    +

    where the variables are as follows:

    +
      +
    • +
      loader (string)The name of the data loader to be used to add this data source to the mesh

      see the abstractScalarDataloader doc page for further information about the available data loaders.

      +
      +
      +
    • +
    • params (dict) : A dictionary containing optional parameters which may be required by the specified data loader in ‘loader’. These parameters include the following:

      +
      +
        +
      • value_fill_types (string) : Determines the actions taken if a cellbox is generated with no data. The possible values are either parent (which implies assigning the value of the parent cellbox), zero or nan.

      • +
      • aggregate_type (string) : Specifies how the data within a cellbox will be aggregated. By default aggregation takes place by calculating the mean of all data points within the CellBoxes bounds. aggregate_type allows this default to be changed to other aggregate function (e.g. MIN, MAX, COUNT).

      • +
      • +
        [scalar] splitting_conditions (list)The conditions which determine if a cellbox should be split based on a scalar dataset.
          +
        • threshold (float) : The threshold above or below which CellBoxes will be sub-divided to separate the datapoints into homogeneous cells.

        • +
        • upperBound (float) : A percentage normalised between 0 and 1. A CellBox is deemed homogeneous if greater than this percentage of data points are above the given threshold.

        • +
        • lowerBound (float) : A percentage normalised between 0 and 1. A Cellbox is deemed homogeneous if less than this percentage of data points are below the given threshold.

        • +
        +
        +
        +
      • +
      • +
        [vector] splitting_conditions (list)The conditions which determine if a cellbox should be split based on a vector dataset.
          +
        • curl (float) : The threshold value above which a cellbox will split. Is calculated as the maximum value of Curl(F) within a cellbox (where F is the vector field).

        • +
        +
        +
        +
      • +
      +
      +
    • +
    +
    +

    Note

    +

    Splitting conditions are applied in the order they are specified in the configuration file.

    +
    +
    +
    +

    5.1.3. Splitting

    +

    Non-uniform mesh refinement is done by selectively sub-dividing cells. Cell +sub-division is performed whenever a cell (of any size) is determined to be +inhomogeneous with respect to a specific characteristic of interest such as +SIC or ocean depth (this characteristic is defined as a splitting condition +inside the data source’s params as illustrated above).

    +

    In the figure below, a graphical representation of the splitting +decision making process is shown. In this, the blue histogram represents an +arbitrary dataset, the orange histogram represents the values in the dataset +that are greater than the threshold (and denoted ‘A’ in the formulae), the +black line is the threshold value, ‘UB’ is the upper bound, and ‘LB’ is the +lower bound. To be specific, this is a probability distribution, and hence the +area under the orange curve ‘A’ is a decimal fraction of the total dataset +(which would have an area of 1).

    +
    +../../_images/splitting_conditions.png +
    +

    Plot showing how cellbox homogeneity is decided

    +
    +
    +
      +
    • If the orange area A <= LB, then the homogeneity condition is CLR.

    • +
    • If the orange area A >= LB, then the homogeneity condition is HOM.

    • +
    • If the orange area LB < A < UB, then the homogeneity condition is HET.

    • +
    +

    CLR, HOM, and HET are used to determine if a cellbox +should be split or not. There is also a fourth homogeneity condition MIN +which is only triggered when the number of datapoints within the cellbox is lower +than the minimum_datapoints specified in the config. The values are checked in this order:

    +
      +
    1. MIN - Do not split the cellbox

    2. +
    3. CLR - Do not split the cellbox, but allow splitting if other datasets return HET

    4. +
    5. HOM - Do not split the cellbox

    6. +
    7. HET - Split the cellbox

    8. +
    +

    In the extreme case where UB = 1 and LB = 0, the cellbox will +always split if there are any datapoints above or below the UB/LB respectively. +Imagining a plot similar to the figure above,

    +
      +
    • If the histogram is entirely blue, return 'CLR'

    • +
    • If the histogram is entirely orange, return 'HOM'

    • +
    • If there’s both colours, return 'HET'

    • +
    +

    The splitting section of the Configuration file defines the splitting parameters that are common across all the data sources and determines how the CellBoxes that form the +Mesh will be sub-divided based on the homogeneity of the data points contained within to form a mesh +of non-uniform spatial resolution.

    +
    "splitting": {
    +   "split_depth":6,
    +   "minimum_datapoints":5
    + }
    +
    +
    +

    where the variables are as follows:

    +
      +
    • split_depth (float) : The number of times the MeshBuilder will sub-divide each initial cellbox (subject to satisfying the splitting conditions of each data source)

    • +
    • minimum_datapoints (float) : The minimum number of datapoints a cellbox must contain for each value type to be able to split

    • +
    +
    +
    + + +
    +
    + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/docs/html/sections/Dataloaders/AddingDataloaders.html b/docs/html/sections/Dataloaders/AddingDataloaders.html new file mode 100644 index 00000000..52bc9228 --- /dev/null +++ b/docs/html/sections/Dataloaders/AddingDataloaders.html @@ -0,0 +1,220 @@ + + + + + + + 7.6. Adding New Dataloaders — meshiphi 1.1.5 documentation + + + + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    + +
    +
    +
    +
    + +
    +

    7.6. Adding New Dataloaders

    +
    +

    7.6.1. Adding to the repository

    +

    Each dataloader is to be implemented as a separate object for the Environmental mesh to interface with. +The general workflow for creating a new dataloader is as follows:

    +
      +
    1. Choose an appropriate dataloader type (see Dataloader Types).

    2. +
    3. Create a new file under meshiphi.DataLoaders/{dataloader-type} with an appropriate name.

    4. +
    5. Create import_data() and (optionally) add_default_params() methods. Examples of how to do this are shown on the abstractScalar and abstractVector pages.

    6. +
    7. Add a new entry to the dataloader factory object, within meshiphi.Dataloaders/Factory.py. Instructions on how to do so are shown in Dataloader Factory

    8. +
    +

    After performing these actions, the dataloader should be ready to go. It is useful for debugging purposes +to create the dataloader object from within meshiphi.Dataloaders/Factory.py (e.g. within +if __name__=='__main__': ) and test its functionality before deploying it.

    +
    +
    +

    7.6.2. Adding within iPython Notebooks

    +

    If you do not wish to modify the repo to add a dataloader, you may add one into the mesh by calling the +add_dataloader() method of MeshBuilder.

    +

    An example of how to do this is detailed below. Assuming you’re working out of a Jupyter notebook, the +basic steps would be to

    +
      +
    1. Create a dataloader

      +
      # Import the abstract dataloader as the base class
      +from meshiphi.dataloaders.scalar.abstract_scalar import ScalarDataLoader
      +
      +# Set up dataloader in the same way as the existing dataloaders
      +class MyDataLoader(ScalarDataLoader):
      +   # Only user defined function required
      +   def import_data(self, bounds):
      +      # Read in data
      +      if len(self.files) == 1:    data = xr.open_dataset(self.files[0])
      +      else:                       data = xr.open_mfdataset(self.files)
      +      # Trim data to boundary
      +      data = self.trim_datapoints(bounds, data=data)
      +
      +      return data
      +
      +
      +
    2. +
    3. Create a dictionary of parameters to initialise the dataloader

      +
      # Params formatted same way as dataloaders in config
      +params = {
      +   'files': [
      +      'PATH_TO_FILE_1',
      +      'PATH_TO_FILE_2',
      +      ... # Populate with as many files as you need
      +   ],
      +   'data_name': 'my_data',
      +   'splitting_conditions':[
      +      {
      +      'my_data':{
      +         'threshold': 0.5,
      +         'upper_bound': 0.9,
      +         'lower_bound': 0.1
      +         }
      +      }
      +   ]
      +}
      +
      +
      +
    4. +
    5. Initialise an Environmental Mesh

      +
      import json
      +from meshiphi.import MeshBuilder
      +
      +# Config to initialise mesh from
      +with open('config.json', 'r') as fp:
      +   config = json.load(fp)
      +
      +# Build a mesh from the config
      +mesh_builder = MeshBuilder(config)
      +env_mesh = mesh_builder.build_environmental_mesh()
      +
      +
      +
    6. +
    7. Add dataloader to mesh

      +
      # Set up bounds of data in dataloader
      +from meshiphi.import Boundary
      +bounds = Boundary.from_json(config)
      +
      +# Add dataloader to mesh builder and regenerate mesh
      +modified_builder = mesh_builder.add_dataloader(MyDataLoader, params, bounds)
      +modified_mesh = modified_builder.build_environmental_mesh()
      +
      +
      +
    8. +
    +
    +
    + + +
    +
    + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/docs/html/sections/Dataloaders/lut/abstractLUT.html b/docs/html/sections/Dataloaders/lut/abstractLUT.html new file mode 100644 index 00000000..42ac0306 --- /dev/null +++ b/docs/html/sections/Dataloaders/lut/abstractLUT.html @@ -0,0 +1,419 @@ + + + + + + + 7.5.1.1. Abstract Look Up Table Dataloader — meshiphi 1.1.5 documentation + + + + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    + +
    +
    +
    +
    + +
    +

    7.5.1.1. Abstract Look Up Table Dataloader

    +
    +
    +class meshiphi.dataloaders.lut.abstract_lut.LutDataLoader(bounds, params)
    +

    Abstract class for all LookUp Table Datasets.

    +
    +
    +__init__(bounds, params)
    +

    This is where large-scale operations are performed, +such as importing data, downsampling, reprojecting, and renaming +variables

    +
    +
    Parameters:
    +
      +
    • bounds (Boundary) – Initial mesh boundary to limit scope of data ingest

    • +
    • params (dict) – Values needed by dataloader to initialise. Unique to each +dataloader

    • +
    +
    +
    +
    +
    +self.data
    +

    Data stored by dataloader to use when called upon by the mesh. +Must be saved in mercator projection (EPSG:4326), with +columns ‘geometry’ and data_name.

    +
    +
    Type:
    +

    gpd.DataFrame

    +
    +
    +
    + +
    +
    +self.data_name
    +

    Name of scalar variable. Must be the column name in the dataframe

    +
    +
    Type:
    +

    str

    +
    +
    +
    + +
    +
    Raises:
    +

    ValueError – If no data lies within the parsed boundary

    +
    +
    +
    + +
    +
    +add_default_params(params)
    +

    Set default values for all LUT dataloaders. This function should be +overloaded to include any extra params for a specific dataloader

    +
    +
    Parameters:
    +

    params (dict) – Dictionary containing attributes that are required for each +dataloader.

    +
    +
    Returns:
    +

    Dictionary of attributes the dataloader will require, +completed with default values if not provided in config.

    +
    +
    Return type:
    +

    (dict)

    +
    +
    +
    + +
    +
    +calculate_coverage(bounds, data=None)
    +

    Calculates percentage of boundary covered by dataset

    +
    +
    Parameters:
    +
      +
    • bounds (Boundary) – Boundary being compared against

    • +
    • data (pd.DataFrame) – Dataset with shapely polygons in ‘geometry’ column +Defaults to objects internal dataset.

    • +
    +
    +
    Returns:
    +

    Decimal fraction of boundary covered by the dataset

    +
    +
    Return type:
    +

    float

    +
    +
    +
    + +
    +
    +downsample()
    +

    Downsampling not supported by LookUpTable Dataloader

    +
    + +
    +
    +get_data_col_name()
    +

    Retrieve name of data column. +Used for when data_name not defined in params.

    +
    +
    Returns:
    +

    Name of data column

    +
    +
    Return type:
    +

    str

    +
    +
    Raises:
    +

    AssertionError – If multiple possible data columns found, can’t retrieve data + name

    +
    +
    +
    + +
    +
    +get_hom_condition(bounds, splitting_conds)
    +

    Retrieves homogeneity condition of data within +boundary.

    +
    +
    Parameters:
    +
      +
    • bounds (Boundary) – Boundary object with limits of datarange to analyse

    • +
    • splitting_conds (dict) –

      Containing the following keys:

      +
      +
      ’boundary’:

      (boolean) True if user wants to split when polygon boundary +goes through bounds

      +
      +
      +

    • +
    +
    +
    Returns:
    +

    The homogeniety condtion returned is of the form:

    +

    ’CLR’ = the boundary is completely contained within the LUT +regions, no need to split

    +

    ’MIN’ = the boundary contains no LUT data, can’t split

    +

    ’HET’ = the boundary contains an edge within the LUT data, +should split

    +

    +
    +
    Return type:
    +

    str

    +
    +
    +
    + +
    +
    +get_val_from_coord(long=None, lat=None, return_coords=False)
    +

    Extracts value from self.data with lat and long specified in kwargs.

    +
    +
    Parameters:
    +
      +
    • long (float) – Longitude coordinate to search for

    • +
    • lat (float) – Latitude coordinate to search for

    • +
    • return_coords (boolean) – Flag for whether to return coordinates with the value or not

    • +
    +
    +
    Returns:
    +

    Either with one entry (the value at the coords), +Optionaly with coordinates associated with it if +return_coords = True

    +
    +
    Return type:
    +

    pd.DataFrame

    +
    +
    +
    + +
    +
    +get_value(bounds, agg_type=None, skipna=False)
    +

    Retrieve aggregated value from within bounds

    +
    +
    Parameters:
    +
      +
    • aggregation_type (str) – Method of aggregation of datapoints within +bounds. Can be upper or lower case. +Accepts ‘MIN’, ‘MAX’, ‘MEAN’, ‘MEDIAN’, ‘STD’, ‘COUNT’

    • +
    • bounds (Boundary) – Boundary object with limits of lat/long

    • +
    • skipna (bool) – Defines whether to propogate NaN’s or not +Default = False (includes NaN’s)

    • +
    +
    +
    Returns:
    +

    {variable (str): aggregated_value (float)} +Aggregated value within bounds following aggregation_type

    +
    +
    Return type:
    +

    dict

    +
    +
    Raises:
    +

    ValueError – aggregation type not in list of available methods

    +
    +
    +
    + +
    +
    +abstract import_data(bounds)
    +

    User defined method for importing data from files, or even generating +data from scratch

    +
    +
    Returns:
    +

    Coordinates and data being imported from file

    +
    +
    if pd.DataFrame,
      +
    • Must have columns ‘geometry’ and data_name

    • +
    • Must have single data column

    • +
    +
    +
    +

    +
    +
    Return type:
    +

    pd.DataFrame

    +
    +
    +
    + +
    +
    +reproject()
    +

    Reprojection not supported by LookUpTable Dataloader

    +
    + +
    +
    +set_data_col_name(new_name)
    +

    Sets name of data column/data variable

    +
    +
    Parameters:
    +

    name (str) – Name to replace currently stored name with

    +
    +
    Returns:
    +

    Data with variable name changed

    +
    +
    Return type:
    +

    pd.DataFrame

    +
    +
    +
    + +
    +
    +trim_datapoints(bounds, data=None)
    +

    Trims datapoints from self.data within boundary defined by ‘bounds’. +self.data can be pd.DataFrame or xr.Dataset

    +
    +
    Parameters:
    +

    bounds (Boundary) – Limits of lat/long/time to select data from

    +
    +
    Returns:
    +

    Trimmed dataset in same format as self.data

    +
    +
    Return type:
    +

    pd.DataFrame

    +
    +
    +
    + +
    +
    +verify_data(data=None)
    +

    Verifies that all geometries read in are Polygons or MultiPolygons +If MultiPolygon, then split out into multiple Polygons

    +
    +
    Parameters:
    +

    data (pd.DataFrame, optional) – DataFrame with at least columns ‘geometry’ and a variable. +Defaults to dataloader’s data attribute.

    +
    +
    Raises:
    +

    ValueError – If read in a geometry that is not Polygon or MultiPolygon

    +
    +
    +
    + +
    + +
    + + +
    +
    + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/docs/html/sections/Dataloaders/lut/implemented/Density.html b/docs/html/sections/Dataloaders/lut/implemented/Density.html new file mode 100644 index 00000000..61efeb02 --- /dev/null +++ b/docs/html/sections/Dataloaders/lut/implemented/Density.html @@ -0,0 +1,170 @@ + + + + + + + 7.5.3.1. Density Dataloader — meshiphi 1.1.5 documentation + + + + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    + +
    +
    +
    +
    + +
    +

    7.5.3.1. Density Dataloader

    +

    Density values were taken from the paper ‘Thickness distribution of Antarctic sea ice’ +(Worby, A.P. et al.). This paper took a density model from the paper ‘Structure, principal +properties and strength of Antarctic sea ice’ (Buynitskiy, V.K.).

    +

    Data is generated using the values from this paper, and so no data file is available for download.

    +
    +
    +class meshiphi.dataloaders.lut.density.DensityDataLoader(bounds, params)
    +
    +
    +import_data(bounds)
    +

    Creates a simulated dataset of sea ice density based on +scientific literature.

    +
    +
    Parameters:
    +

    bounds (Boundary) – Initial boundary to limit the dataset to

    +
    +
    Returns:
    +

    Sea Ice Density dataset within limits of bounds. +DataFrame has coordinates ‘date’, ‘shape’, +and variable ‘density’

    +
    +
    Return type:
    +

    density_df (pd.DataFrame)

    +
    +
    +
    + +
    + +
    + + +
    +
    + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/docs/html/sections/Dataloaders/lut/implemented/LutCSV.html b/docs/html/sections/Dataloaders/lut/implemented/LutCSV.html new file mode 100644 index 00000000..fcf49934 --- /dev/null +++ b/docs/html/sections/Dataloaders/lut/implemented/LutCSV.html @@ -0,0 +1,172 @@ + + + + + + + 7.5.3.2. LUT CSV Dataloader — meshiphi 1.1.5 documentation + + + + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    + +
    +
    +
    +
    + +
    +

    7.5.3.2. LUT CSV Dataloader

    +

    The scalar CSV dataloader is designed to take any .csv file and cast +it into a data source for mesh construction. It was primarily used in testing +for loading dummy data to test performance. As such, there is no data source +for this dataloader. The CSV must have two columns: ‘geometry’ and ‘data_name’. +‘geometry’ must have that title, and is a shapely wkt string. data_name can have +any name, and is just the value that is associated with the polygon.

    +
    +
    +class meshiphi.dataloaders.lut.lut_csv.LutCSV(bounds, params)
    +
    +
    +import_data(bounds)
    +

    Import a list of .csv files, assign regions a value specified in +config params, regions outside this are numpy nan values.

    +
    +
    Parameters:
    +

    bounds (Boundary) – Initial boundary to limit the dataset to

    +
    +
    Returns:
    +

    Dataframe of polygons with value specified in config. +DataFrame has columns ‘geometry’ and +data_name (read from CSV by default)

    +
    +
    Return type:
    +

    exclusion_df (pd.DataFrame)

    +
    +
    +
    + +
    + +
    + + +
    +
    + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/docs/html/sections/Dataloaders/lut/implemented/LutGeoJSON.html b/docs/html/sections/Dataloaders/lut/implemented/LutGeoJSON.html new file mode 100644 index 00000000..f668f910 --- /dev/null +++ b/docs/html/sections/Dataloaders/lut/implemented/LutGeoJSON.html @@ -0,0 +1,191 @@ + + + + + + + 7.5.3.3. LUT GeoJSON Dataloader — meshiphi 1.1.5 documentation + + + + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    + +
    +
    +
    +
    + +
    +

    7.5.3.3. LUT GeoJSON Dataloader

    +

    The scalar CSV dataloader is designed to take any geojson file and cast +it into a data source for mesh construction. It was primarily used in testing +for loading dummy data to test performance. When using this dataloader, a value +should be provided in the mesh config file that specifies the value and data_name +that the polygons save. The keyword in the config params is ‘value’.

    +
    +
    +class meshiphi.dataloaders.lut.lut_geojson.LutGeoJSON(bounds, params)
    +
    +
    +add_default_params(params)
    +

    Set default values for LUT dataloader. Only unique addition over +the regular abstracted add_default_params is the data_name

    +
    +
    Parameters:
    +

    params (dict) – Dictionary containing attributes that are required for the +LUT being loaded.

    +
    +
    Returns:
    +

    Dictionary of attributes the dataloader will require, +completed with default values if not provided in config.

    +
    +
    Return type:
    +

    (dict)

    +
    +
    +
    + +
    +
    +import_data(bounds)
    +

    Import a list of GeoJSON files, assign regions a value specified in +config params, regions outside this are numpy nan values.

    +
    +
    Parameters:
    +

    bounds (Boundary) – Initial boundary to limit the dataset to

    +
    +
    Returns:
    +

    Dataframe of polygons with value specified in config. +DataFrame has columns ‘geometry’ and +data_name (‘dummy_data’ by default)

    +
    +
    Return type:
    +

    exclusion_df (pd.DataFrame)

    +
    +
    +
    + +
    + +
    + + +
    +
    + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/docs/html/sections/Dataloaders/lut/implemented/Scotland_NCMPA.html b/docs/html/sections/Dataloaders/lut/implemented/Scotland_NCMPA.html new file mode 100644 index 00000000..ae669315 --- /dev/null +++ b/docs/html/sections/Dataloaders/lut/implemented/Scotland_NCMPA.html @@ -0,0 +1,168 @@ + + + + + + + 7.5.3.4. Scotland NCMPA Dataloader — meshiphi 1.1.5 documentation + + + + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    + +
    +
    +
    +
    + +
    +

    7.5.3.4. Scotland NCMPA Dataloader

    +

    GeoJSON files are provided by the Scottish government for Nature Conservation Marine Protected Areas.

    +

    Data can be downloaded from here

    +
    +
    +class meshiphi.dataloaders.lut.scotland_ncmpa.ScotlandNCMPA(bounds, params)
    +
    +
    +import_data(bounds)
    +

    Creates a simulated dataset of sea ice thickness based on +scientific literature.

    +
    +
    Parameters:
    +

    bounds (Boundary) – Initial boundary to limit the dataset to

    +
    +
    Returns:
    +

    Dataframe of exclusion zones around scotland. +DataFrame has coordinates ‘date’, ‘shape’, +and variable ‘thickness’

    +
    +
    Return type:
    +

    exclusion_df (pd.DataFrame)

    +
    +
    +
    + +
    + +
    + + +
    +
    + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/docs/html/sections/Dataloaders/lut/implemented/Thickness.html b/docs/html/sections/Dataloaders/lut/implemented/Thickness.html new file mode 100644 index 00000000..765e7075 --- /dev/null +++ b/docs/html/sections/Dataloaders/lut/implemented/Thickness.html @@ -0,0 +1,200 @@ + + + + + + + 7.5.3.5. Thickness Dataloader — meshiphi 1.1.5 documentation + + + + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    + +
    +
    +
    +
    + +
    +

    7.5.3.5. Thickness Dataloader

    +

    Thickness values were taken from the paper ‘Thickness distribution of Antarctic sea ice’ +(Worby, A.P. et al.).

    +

    Data is generated using the values from this paper, and so no +data file is available for download.

    +
    +
    +class meshiphi.dataloaders.lut.thickness.ThicknessDataLoader(bounds, params)
    +
    +
    +class Region(name, geometry, value_dict, seasons={1: 'su', 2: 'su', 3: 'au', 4: 'au', 5: 'au', 6: 'wi', 7: 'wi', 8: 'wi', 9: 'sp', 10: 'sp', 11: 'sp', 12: 'su'})
    +

    Data storage object with region boundary as polygon, seasonal +sea ice densities, and a dict mapping from integer month to season

    +
    +
    +__init__(name, geometry, value_dict, seasons={1: 'su', 2: 'su', 3: 'au', 4: 'au', 5: 'au', 6: 'wi', 7: 'wi', 8: 'wi', 9: 'sp', 10: 'sp', 11: 'sp', 12: 'su'})
    +
    + +
    +
    +get_value(month)
    +

    Returns the sea ice density for a given month, taking into account +seasons per hemisphere

    +
    +
    Parameters:
    +

    month (int) – Month as an integer (1 = Jan … 12 = Dec)

    +
    +
    Returns:
    +

    Sea Ice Density in the specified season

    +
    +
    Return type:
    +

    float

    +
    +
    +
    + +
    + +
    +
    +import_data(bounds)
    +

    Creates a simulated dataset of sea ice thickness based on +scientific literature.

    +
    +
    Parameters:
    +

    bounds (Boundary) – Initial boundary to limit the dataset to

    +
    +
    Returns:
    +

    Sea Ice thickness dataset within limits of bounds. +DataFrame has coordinates ‘date’, ‘geometry’, +and variable ‘thickness’

    +
    +
    Return type:
    +

    thickness_df (pd.DataFrame)

    +
    +
    +
    + +
    + +
    + + +
    +
    + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/docs/html/sections/Dataloaders/lut/index.html b/docs/html/sections/Dataloaders/lut/index.html new file mode 100644 index 00000000..39cbff7c --- /dev/null +++ b/docs/html/sections/Dataloaders/lut/index.html @@ -0,0 +1,177 @@ + + + + + + + 7.5. LUT Dataloaders — meshiphi 1.1.5 documentation + + + + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    + +
    +
    +
    +
    + +
    +

    7.5. LUT Dataloaders

    +
    +

    7.5.1. Abstract LUT Base Class

    + +

    The Abstract Base Class of the Look Up Table dataloaders holds most of the +functionality that would be needed to manipulate the data to work +with the mesh. When creating a new dataloader, the user must define +how to open the data files, and what methods are required to manipulate +the data into a standard format. More details are provided on the +abstractVector doc page

    +
    +
    +

    7.5.2. LUT Dataloader Examples

    +

    Creating a LUT dataloader is almost identical to creating a +scalar dataloader. The key differences +are that the LUTDataLoader abstract base class must be used, and +regions are defined by Shapely polygons. Data is imported and saved as +GeoPandas dataframes, holding a polygon and an associated value.

    +
    +
    +

    7.5.3. Implemented LUT Dataloaders

    + +
    +
    + + +
    +
    + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/docs/html/sections/Dataloaders/scalar/implemented/ECMWFSigWaveHeight.html b/docs/html/sections/Dataloaders/scalar/implemented/ECMWFSigWaveHeight.html new file mode 100644 index 00000000..564c0164 --- /dev/null +++ b/docs/html/sections/Dataloaders/scalar/implemented/ECMWFSigWaveHeight.html @@ -0,0 +1,165 @@ + + + + + + + 7.3.3.6. ECMWFSigWaveHeight Dataloader — meshiphi 1.1.5 documentation + + + + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    + +
    +
    +
    +
    + +
    +

    7.3.3.6. ECMWFSigWaveHeight Dataloader

    +

    The ECMWF (European Centre for Medium-Range Weather Forecasts) are both a +research institute and a 24/7 operational service, producing global numerical +weather predictions and other data for their Member and Co-operating States +and the broader community. The Centre has one of the largest supercomputer +facilities and meteorological data archives in the world. Other strategic +activities include delivering advanced training and assisting the WMO in +implementing its programmes. +(description taken from here)

    +

    Data can be downloaded from here

    +

    This dataloader is for the grib2 files.

    +
    + + +
    +
    + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/docs/html/sections/Dataloaders/scalar/implemented/ERA5MaxWaveHeight.html b/docs/html/sections/Dataloaders/scalar/implemented/ERA5MaxWaveHeight.html new file mode 100644 index 00000000..07c80a9f --- /dev/null +++ b/docs/html/sections/Dataloaders/scalar/implemented/ERA5MaxWaveHeight.html @@ -0,0 +1,191 @@ + + + + + + + 7.3.3.7. ERA5 Maximum Wave Height Dataloader — meshiphi 1.1.5 documentation + + + + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    + +
    +
    +
    +
    + +
    +

    7.3.3.7. ERA5 Maximum Wave Height Dataloader

    +

    ERA5 is a family of data products produced by the European Centre for Medium-Range Weather Forecasts (ECMWF). +It is the fifth generation ECMWF atmospheric reanalysis of the global climate covering the period from January 1950 to present.

    +

    From their website:

    +
    +

    ERA5 provides hourly estimates of a large number of atmospheric, +land and oceanic climate variables. The data cover the Earth on a +30km grid and resolve the atmosphere using 137 levels from the +surface up to a height of 80km. ERA5 includes information about +uncertainties for all variables at reduced spatial and temporal resolutions.

    +
    +

    Instructions for how to download their data products are +available here

    +
    +
    +class meshiphi.dataloaders.scalar.era5_max_wave_height.ERA5MaxWaveHeightDataLoader(bounds, params)
    +
    +
    +import_data(bounds)
    +

    Reads in data from an ERA5 NetCDF file. +Renames coordinates to ‘lat’ and ‘long’

    +
    +
    Parameters:
    +

    bounds (Boundary) – Initial boundary to limit the dataset to

    +
    +
    Returns:
    +

    ERA5 wave dataset within limits of bounds. +Dataset has coordinates ‘lat’, ‘long’, and variable ‘hmax’

    +
    +
    Return type:
    +

    xr.Dataset

    +
    +
    +
    + +
    + +
    + + +
    +
    + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/docs/html/sections/Dataloaders/scalar/implemented/ERA5SigWaveHeight.html b/docs/html/sections/Dataloaders/scalar/implemented/ERA5SigWaveHeight.html new file mode 100644 index 00000000..cf07bace --- /dev/null +++ b/docs/html/sections/Dataloaders/scalar/implemented/ERA5SigWaveHeight.html @@ -0,0 +1,191 @@ + + + + + + + 7.3.3.8. ERA5 Significant Wave Height Dataloader — meshiphi 1.1.5 documentation + + + + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    + +
    +
    +
    +
    + +
    +

    7.3.3.8. ERA5 Significant Wave Height Dataloader

    +

    ERA5 is a family of data products produced by the European Centre for Medium-Range Weather Forecasts (ECMWF). +It is the fifth generation ECMWF atmospheric reanalysis of the global climate covering the period from January 1950 to present.

    +

    From their website:

    +
    +

    ERA5 provides hourly estimates of a large number of atmospheric, +land and oceanic climate variables. The data cover the Earth on a +30km grid and resolve the atmosphere using 137 levels from the +surface up to a height of 80km. ERA5 includes information about +uncertainties for all variables at reduced spatial and temporal resolutions.

    +
    +

    Instructions for how to download their data products are +available here

    +
    +
    +class meshiphi.dataloaders.scalar.era5_sig_wave_height.ERA5SigWaveHeightDataLoader(bounds, params)
    +
    +
    +import_data(bounds)
    +

    Reads in data from an ERA5 NetCDF file. +Renames coordinates to ‘lat’ and ‘long’

    +
    +
    Parameters:
    +

    bounds (Boundary) – Initial boundary to limit the dataset to

    +
    +
    Returns:
    +

    ERA5 wave dataset within limits of bounds. +Dataset has coordinates ‘lat’, ‘long’, and variable ‘swh’

    +
    +
    Return type:
    +

    xr.Dataset

    +
    +
    +
    + +
    + +
    + + +
    +
    + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/docs/html/sections/Dataloaders/scalar/implemented/ERA5WaveDirection.html b/docs/html/sections/Dataloaders/scalar/implemented/ERA5WaveDirection.html new file mode 100644 index 00000000..b5369d08 --- /dev/null +++ b/docs/html/sections/Dataloaders/scalar/implemented/ERA5WaveDirection.html @@ -0,0 +1,191 @@ + + + + + + + 7.3.3.9. ERA5 Mean Wave Direction Dataloader — meshiphi 1.1.5 documentation + + + + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    + +
    +
    +
    +
    + +
    +

    7.3.3.9. ERA5 Mean Wave Direction Dataloader

    +

    ERA5 is a family of data products produced by the European Centre for Medium-Range Weather Forecasts (ECMWF). +It is the fifth generation ECMWF atmospheric reanalysis of the global climate covering the period from January 1950 to present.

    +

    From their website:

    +
    +

    ERA5 provides hourly estimates of a large number of atmospheric, +land and oceanic climate variables. The data cover the Earth on a +30km grid and resolve the atmosphere using 137 levels from the +surface up to a height of 80km. ERA5 includes information about +uncertainties for all variables at reduced spatial and temporal resolutions.

    +
    +

    Instructions for how to download their data products are +available here

    +
    +
    +class meshiphi.dataloaders.scalar.era5_mean_wave_direction.ERA5MeanWaveDirDataLoader(bounds, params)
    +
    +
    +import_data(bounds)
    +

    Reads in data from an ERA5 NetCDF file. +Renames coordinates to ‘lat’ and ‘long’

    +
    +
    Parameters:
    +

    bounds (Boundary) – Initial boundary to limit the dataset to

    +
    +
    Returns:
    +

    ERA5 wave dataset within limits of bounds. +Dataset has coordinates ‘lat’, ‘long’, and variable ‘mwd’

    +
    +
    Return type:
    +

    xr.Dataset

    +
    +
    +
    + +
    + +
    + + +
    +
    + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/docs/html/sections/Dataloaders/scalar/implemented/ERA5WavePeriod.html b/docs/html/sections/Dataloaders/scalar/implemented/ERA5WavePeriod.html new file mode 100644 index 00000000..7dea131e --- /dev/null +++ b/docs/html/sections/Dataloaders/scalar/implemented/ERA5WavePeriod.html @@ -0,0 +1,191 @@ + + + + + + + 7.3.3.10. ERA5 Mean Wave Period Dataloader — meshiphi 1.1.5 documentation + + + + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    + +
    +
    +
    +
    + +
    +

    7.3.3.10. ERA5 Mean Wave Period Dataloader

    +

    ERA5 is a family of data products produced by the European Centre for Medium-Range Weather Forecasts (ECMWF). +It is the fifth generation ECMWF atmospheric reanalysis of the global climate covering the period from January 1950 to present.

    +

    From their website:

    +
    +

    ERA5 provides hourly estimates of a large number of atmospheric, +land and oceanic climate variables. The data cover the Earth on a +30km grid and resolve the atmosphere using 137 levels from the +surface up to a height of 80km. ERA5 includes information about +uncertainties for all variables at reduced spatial and temporal resolutions.

    +
    +

    Instructions for how to download their data products are +available here

    +
    +
    +class meshiphi.dataloaders.scalar.era5_wave_period.ERA5WavePeriodDataLoader(bounds, params)
    +
    +
    +import_data(bounds)
    +

    Reads in data from an ERA5 NetCDF file. +Renames coordinates to ‘lat’ and ‘long’

    +
    +
    Parameters:
    +

    bounds (Boundary) – Initial boundary to limit the dataset to

    +
    +
    Returns:
    +

    ERA5 wave dataset within limits of bounds. +Dataset has coordinates ‘lat’, ‘long’, and variable ‘mwp’

    +
    +
    Return type:
    +

    xr.Dataset

    +
    +
    +
    + +
    + +
    + + +
    +
    + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/docs/html/sections/Dataloaders/scalar/implemented/ERA5WindDirection.html b/docs/html/sections/Dataloaders/scalar/implemented/ERA5WindDirection.html new file mode 100644 index 00000000..469f85a3 --- /dev/null +++ b/docs/html/sections/Dataloaders/scalar/implemented/ERA5WindDirection.html @@ -0,0 +1,191 @@ + + + + + + + 7.3.3.11. ERA5 Wind Direction Dataloader — meshiphi 1.1.5 documentation + + + + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    + +
    +
    +
    +
    + +
    +

    7.3.3.11. ERA5 Wind Direction Dataloader

    +

    ERA5 is a family of data products produced by the European Centre for Medium-Range Weather Forecasts (ECMWF). +It is the fifth generation ECMWF atmospheric reanalysis of the global climate covering the period from January 1950 to present.

    +

    From their website:

    +
    +

    ERA5 provides hourly estimates of a large number of atmospheric, +land and oceanic climate variables. The data cover the Earth on a +30km grid and resolve the atmosphere using 137 levels from the +surface up to a height of 80km. ERA5 includes information about +uncertainties for all variables at reduced spatial and temporal resolutions.

    +
    +

    Instructions for how to download their data products are +available here

    +
    +
    +class meshiphi.dataloaders.scalar.era5_wind_dir.ERA5WindDirDataLoader(bounds, params)
    +
    +
    +import_data(bounds)
    +

    Reads in data from an ERA5 NetCDF file. +Renames coordinates to ‘lat’ and ‘long’

    +
    +
    Parameters:
    +

    bounds (Boundary) – Initial boundary to limit the dataset to

    +
    +
    Returns:
    +

    ERA5 wave dataset within limits of bounds. +Dataset has coordinates ‘lat’, ‘long’, and variable ‘wind_dir’

    +
    +
    Return type:
    +

    xr.Dataset

    +
    +
    +
    + +
    + +
    + + +
    +
    + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/docs/html/sections/Dataloaders/scalar/implemented/ERA5WindMagnitude.html b/docs/html/sections/Dataloaders/scalar/implemented/ERA5WindMagnitude.html new file mode 100644 index 00000000..492be8c8 --- /dev/null +++ b/docs/html/sections/Dataloaders/scalar/implemented/ERA5WindMagnitude.html @@ -0,0 +1,191 @@ + + + + + + + 7.3.3.12. ERA5 Wind Magnitude Dataloader — meshiphi 1.1.5 documentation + + + + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    + +
    +
    +
    +
    + +
    +

    7.3.3.12. ERA5 Wind Magnitude Dataloader

    +

    ERA5 is a family of data products produced by the European Centre for Medium-Range Weather Forecasts (ECMWF). +It is the fifth generation ECMWF atmospheric reanalysis of the global climate covering the period from January 1950 to present.

    +

    From their website:

    +
    +

    ERA5 provides hourly estimates of a large number of atmospheric, +land and oceanic climate variables. The data cover the Earth on a +30km grid and resolve the atmosphere using 137 levels from the +surface up to a height of 80km. ERA5 includes information about +uncertainties for all variables at reduced spatial and temporal resolutions.

    +
    +

    Instructions for how to download their data products are +available here

    +
    +
    +class meshiphi.dataloaders.scalar.era5_wind_mag.ERA5WindMagDataLoader(bounds, params)
    +
    +
    +import_data(bounds)
    +

    Reads in data from an ERA5 NetCDF file. +Renames coordinates to ‘lat’ and ‘long’

    +
    +
    Parameters:
    +

    bounds (Boundary) – Initial boundary to limit the dataset to

    +
    +
    Returns:
    +

    ERA5 wave dataset within limits of bounds. +Dataset has coordinates ‘lat’, ‘long’, and variable ‘wind_mag’

    +
    +
    Return type:
    +

    xr.Dataset

    +
    +
    +
    + +
    + +
    + + +
    +
    + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/docs/html/sections/Dataloaders/scalar/implemented/visual_iced.html b/docs/html/sections/Dataloaders/scalar/implemented/visual_iced.html new file mode 100644 index 00000000..2be84307 --- /dev/null +++ b/docs/html/sections/Dataloaders/scalar/implemented/visual_iced.html @@ -0,0 +1,167 @@ + + + + + + + 7.3.3.19. Visual_iced Dataloader — meshiphi 1.1.5 documentation + + + + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    + +
    +
    +
    +
    + +
    +

    7.3.3.19. Visual_iced Dataloader

    +

    Visual_iced is a dataloader for .tiff images, which are outputs from the visual_iced library +developed by Martin Rogers at the British Antarctic Survey’s AI Lab. These visual_iced +images are ice/water binary files, generated from a combination of MODIS and SAR +satellite imagery.

    +

    In the source data, 0s are representative of open water, and 1s are representative of +ice. In the dataloader, we map these values to sea ice concentration, in the range of 0 to 100. +Values between 0 and 100 are generated by the aggregation of the 0s and 1s within each cell.

    +
    +

    Note

    +

    The visual_iced dataloader only supports loading in single files, as the visual_iced datasets +are not temporally continuous within a given boundary.

    +
    +
    + + +
    +
    + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/docs/html/sections/Dataloaders/vector/implemented/DUACS.html b/docs/html/sections/Dataloaders/vector/implemented/DUACS.html new file mode 100644 index 00000000..9f9e39c7 --- /dev/null +++ b/docs/html/sections/Dataloaders/vector/implemented/DUACS.html @@ -0,0 +1,182 @@ + + + + + + + 7.4.3.2. DUACS Currents Dataloader — meshiphi 1.1.5 documentation + + + + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    + +
    +
    +
    +
    + +
    +

    7.4.3.2. DUACS Currents Dataloader

    +

    DUACS is a European operational multi-mission production system of altimeter data that provides (amongst other products) +global ocean current vectors. The system was developed by CNES/CLS and data is available from the copernicus marine data +service.

    +
    +
    From their website:

    Altimeter satellite gridded Sea Level Anomalies (SLA) computed with respect to a twenty-year 1993, 2012 mean. The SLA +is estimated by Optimal Interpolation, merging the L3 along-track measurement from the different altimeter missions +available. Part of the processing is fitted to the Global Ocean. The product gives additional variables (i.e. +Absolute Dynamic Topography and geostrophic currents).

    +
    +
    +

    Near real-time data can be downloaded from here.

    +

    Reanalysis data can be downloaded from here.

    +
    +
    +class meshiphi.dataloaders.vector.duacs_current.DuacsCurrentDataLoader(bounds, params)
    +
    +
    +import_data(bounds)
    +

    Reads in data from a DUACS altimeter derived current NetCDF file. +Renames coordinates to ‘lat’ and ‘long’, and renames variable to +‘uC, vC’

    +
    +
    Parameters:
    +

    bounds (Boundary) – Initial boundary to limit the dataset to

    +
    +
    Returns:
    +

    Near real-time current dataset within limits of bounds. +Dataset has coordinates ‘lat’, ‘long’, and variable ‘uC’, ‘vC’

    +
    +
    Return type:
    +

    xr.Dataset

    +
    +
    +
    + +
    + +
    + + +
    +
    + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/docs/html/sections/Dataloaders/vector/implemented/ERA5WaveDirection.html b/docs/html/sections/Dataloaders/vector/implemented/ERA5WaveDirection.html new file mode 100644 index 00000000..03438d8f --- /dev/null +++ b/docs/html/sections/Dataloaders/vector/implemented/ERA5WaveDirection.html @@ -0,0 +1,184 @@ + + + + + + + 7.4.3.3. ERA5 Wave Direction Dataloader — meshiphi 1.1.5 documentation + + + + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    + +
    +
    +
    +
    + +
    +

    7.4.3.3. ERA5 Wave Direction Dataloader

    +

    ERA5 is a family of data products produced by the European Centre for Medium-Range Weather Forecasts (ECMWF). +It is the fifth generation ECMWF atmospheric reanalysis of the global climate covering the period from January 1950 to present.

    +

    From their website:

    +
    +

    ERA5 provides hourly estimates of a large number of atmospheric, +land and oceanic climate variables. The data cover the Earth on a +30km grid and resolve the atmosphere using 137 levels from the +surface up to a height of 80km. ERA5 includes information about +uncertainties for all variables at reduced spatial and temporal resolutions.

    +
    +

    Instructions for how to download their data products are +available here

    +

    This dataloader takes the mean wave direction variable, which gives the direction the waves are coming from as an angle +from north in degrees, and converts it to a unit vector with u and v components.

    +
    +
    +class meshiphi.dataloaders.vector.era5_wave_direction_vector.ERA5WaveDirectionLoader(bounds, params)
    +
    +
    +import_data(bounds)
    +

    Reads in wave direction data from a ERA5 NetCDF file. +Renames coordinates to ‘lat’ and ‘long’ and calculates unit vector +from mean wave direction variable ‘mwd’.

    +
    +
    Parameters:
    +

    bounds (Boundary) – Initial boundary to limit the dataset to

    +
    +
    Returns:
    +

    ERA5 wave dataset within limits of bounds. +Dataset has coordinates ‘lat’, ‘long’, and variables ‘uW’, ‘vW’

    +
    +
    Return type:
    +

    xr.Dataset

    +
    +
    +
    + +
    + +
    + + +
    +
    + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/docs/html/sections/Mesh_Construction/Mesh_construction_classes.html b/docs/html/sections/Mesh_Construction/Mesh_construction_classes.html new file mode 100644 index 00000000..c4f948d1 --- /dev/null +++ b/docs/html/sections/Mesh_Construction/Mesh_construction_classes.html @@ -0,0 +1,943 @@ + + + + + + + 8.4.1. Mesh Construction - Classes — meshiphi 1.1.5 documentation + + + + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    + +
    +
    +
    +
    + +
    +

    8.4.1. Mesh Construction - Classes

    +

    This section describes the main classes of the Mesh Construction module in detail. +For an overview of the abstractions behind the Mesh Construction module, see the +Mesh Construction - Overview section of the documentation.

    +
    +

    8.4.1.1. MeshBuilder

    +

    The MeshBuilder object is the main class of the Mesh Construction module. It is used to build the +EnvironmentalMesh object from a collection geospatial data. Features of the created EnvironmentalMesh +as be set using a configuration file passed to the MeshBuilder object. For more information on the format +of the configuration file, see the Configuration - Mesh Construction section of the documentation.

    +

    In this section we will discuss the usage of the MeshBuilder functionality of meshiphi.

    +

    Example

    +

    An example of how to run this code can be executed by running the following in an ipython/Jupyter Notebook:

    +
    from meshiphi.mesh_generation.mesh_builder import MeshBuilder
    +
    +import json
    +with open('./config.json', 'r') as f:
    +    config = json.load(f)['config']
    +
    +mesh_builder = MeshBuilder(config)
    +mesh_builder.build_environmental_mesh()
    +
    +
    +
    +
    +class meshiphi.mesh_generation.mesh_builder.MeshBuilder(config)
    +

    A class resposible for building an environment mesh based on a provided config file.

    +
    +
    +__init__(config)
    +

    Constructs a Mesh from a given config file.

    +
    +
    Parameters:
    +

    config (dict) –

    config file which defines the attributes of the Mesh to be constructed. config is of the form:

    +
    +

    {

    +

    “region”: {

    +
    +

    “lat_min”: (real),

    +

    ”lat_max”: (real),

    +

    ”long_min”: (real),

    +

    ”long_max”: (real),

    +

    ”start_time”: (string) ‘YYYY-MM-DD’,

    +

    ”end_time”: (string) ‘YYYY-MM-DD’,

    +

    ”cell_width”: (real),

    +

    ”cell_height” (real),

    +

    ”split_depth” (int)

    +
    +

    },

    +

    ”data_sources”: [

    +
    +

    {

    +
    +

    “loader”: (string)

    +

    ”params” (dict)

    +
    +

    }

    +
    +

    ],

    +

    ”splitting”: {

    +
    +

    “split_depth”: (int),

    +

    ”minimum_datapoints”: (int)

    +

    }

    +
    +

    }

    +
    +

    NOTE: In the case of constructing a global mesh, the longtitude range should be -180:180.

    +

    ”j_grid” (bool): True if the Mesh to be constructed should be of the same format as the original Java CellGrid, to be used for regression testing.

    +

    +
    +
    +
    + +
    +
    +add_dataloader(Dataloader, params, bounds=None, name='myDataLoader', min_dp=5)
    +

    Adds a dataloader to a pre-existing mesh by adding to the metadata

    +
    +
    Parameters:
    +
      +
    • Dataloader (ScalarDataLoader or VectorDataLoader) – Dataloader object to add to metadata

    • +
    • params (dict) – Parameters to initialise dataloader with

    • +
    • bounds (Boundary) –

    • +
    • name (str) – Name of the dataloader used in config

    • +
    +
    +
    Returns:
    +

    Original MeshBuilder object (self) with added metadata for +new dataloader

    +
    +
    Return type:
    +

    MeshBuilder

    +
    +
    +
    + +
    +
    +build_environmental_mesh()
    +

    splits the mesh then goes through the mesh cellboxes and builds an evironmental mesh that contains the cellboxes aggregated data

    +
    +
    Returns:
    +

    an object that represents the constructed nonunifrom mesh and contains the aggregated cellboxs and neighbour graph

    +
    +
    Return type:
    +

    EnvironmentMesh

    +
    +
    +
    + +
    +
    +split_and_replace(cellbox)
    +

    Replaces a cellbox given by parameter ‘cellbox’ in this grid with +4 smaller cellboxes representing the four corners of the given cellbox. +A neighbours map is then created for each of the 4 new cellboxes +and the neighbours map for all surrounding cell boxes is updated.

    +
    +
    Parameters:
    +

    cellbox (CellBox) – the CellBox within this Mesh to be split into +4 smaller CellBox objects.

    +
    +
    +
    + +
    +
    +split_to_depth(split_depth)
    +

    splits all cellboxes in this grid until a maximum split depth +is reached, or all cellboxes are homogeneous.

    +
    +
    Parameters:
    +

    split_depth (int) – The maximum split depth reached by any CellBox +within this Mesh after splitting.

    +
    +
    +
    + +
    + +
    +
    +

    8.4.1.2. EnvironmentMesh

    +

    The EnvironmentMesh object is a collection of geospatial boundaries containing an aggregated representation +of the data contained within the boundaries (AggregatedCellBox objects). The EnvironmentMesh object is +created by the MeshBuilder object, though the object is mutable and can be updated after construction.

    +
    +
    +class meshiphi.mesh_generation.environment_mesh.EnvironmentMesh(bounds, agg_cellboxes, neighbour_graph, config)
    +

    a class that defines the environmental mesh structure and contains each cellbox aggregate information

    +
    +
    +bounds
    +

    the boundaries of this mesh

    +
    +
    Type:
    +

    Boundary

    +
    +
    +
    + +
    +
    +agg_cellboxes
    +

    a list of aggregated cellboxes

    +
    +
    Type:
    +

    AggregatedCellBox[]

    +
    +
    +
    + +
    +
    +neighbour_graph
    +

    an object contains each cellbox neighbours information

    +
    +
    Type:
    +

    NeighbourGraph

    +
    +
    +
    + +
    +
    +config
    +

    conatins the initial config used to build this mesh

    +
    +
    Type:
    +

    dict

    +
    +
    +
    + +
    +
    +__init__(bounds, agg_cellboxes, neighbour_graph, config)
    +
    +
    Parameters:
    +
      +
    • bounds (Boundary) – the boundaries of this mesh

    • +
    • agg_cellboxes (AggregatedCellBox[]) – a list of aggregated cellboxes

    • +
    • neighbour_graph (NeighbourGraph) – an object contains each cellbox neighbours information

    • +
    • config (dict) – conatins the initial config used to build this mesh.

    • +
    +
    +
    +
    + +
    +
    +classmethod load_from_json(mesh_json)
    +

    Constructs an Env.Mesh from a given env-mesh json file to be used by other modules (ex.Vessel Performance Modeller).

    +
    +
    Parameters:
    +

    mesh_json (dict) –

    a dictionary loaded from an Env-mesh json file of the following format -

    +

    {

    +
    +

    “mesh_info”: {

    +
    +

    “region”: {

    +
    +

    “lat_min”: (real),

    +

    ”lat_max”: (real),

    +

    ”long_min”: (real),

    +

    ”long_max”: (real),

    +

    ”start_time”: (string) ‘YYYY-MM-DD’,

    +

    ”end_time”: (string) ‘YYYY-MM-DD’,

    +

    ”cell_width”: (real),

    +

    ”cell_height” (real),

    +

    ”split_depth” (int)

    +
    +

    },

    +

    ”data_sources”: [

    +
    +

    {

    +
    +

    “loader”: (string)

    +

    ”params” (dict)

    +
    +

    },

    +

    …,

    +

    {…} +],

    +
    +

    ”splitting”: {

    +
    +

    “split_depth”: (int),

    +

    ”minimum_datapoints”: (int)

    +
    +

    }

    +
    +

    },

    +

    ”cellboxes”: [

    +
    +

    {

    +

    },

    +

    …,

    +

    {…}

    +
    +

    ],

    +

    ”neighbour_graph”: [

    +
    +

    {

    +

    },

    +

    …,

    +

    {…}

    +
    +

    ]

    +
    +

    }

    +

    +
    +
    Returns:
    +

    object that contains all the json file mesh information.

    +
    +
    Return type:
    +

    EnvironmentMesh

    +
    +
    +
    + +
    +
    +save(path, format='JSON', format_params=None)
    +

    Saves this object to a location in local storage in a specific format.

    +
    +
    Parameters:
    +
      +
    • path (String) – The file location the mesh will be saved to.

    • +
    • format (String) (optional) –

      The format the mesh will be saved in. +If not format is given, default is JSON. +Supported formats are

      +
      +
        +
      • JSON

      • +
      • GEOJSON

      • +
      +
      +

    • +
    +
    +
    +
    + +
    +
    +to_geojson(params_file=None)
    +

    Returns the cellboxes of this mesh converted to a geoJSON format.

    +
    +
    Returns:
    +

    The cellboxes of this mesh in a geoJSON format

    +
    +
    Return type:
    +

    geojson

    +
    +
    +
    +

    Note

    +

    geoJSON format does not contain all the data included in the standard +.to_json() format. geoJSON meshes do not contain the configs used to +build them, or the neighbour-graph which details how each of the +cellboxes are connected together.

    +
    +
    + +
    +
    +to_json()
    +

    Returns this Mesh converted to a JSON object.

    +
    +
    Returns:
    +

    a string representation of the CellGird parseable as a JSON object. The JSON object is of the form -

    +
    +

    {

    +
    +

    “config”: the config used to initialize the Mesh,

    +

    ”cellboxes”: a list of CellBoxes contained within the Mesh,

    +

    ”neighbour_graph”: a graph representing the adjacency of CellBoxes within the Mesh.

    +
    +

    }

    +
    +

    +
    +
    Return type:
    +

    json

    +
    +
    +
    + +
    +
    +to_tif(params_file, path)
    +

    generates a representation of the mesh in geotif image format.

    +
    +
    Parameters:
    +
      +
    • params_file (string) (optional) –

      a path to a file that contains a dict of the folowing export parameters (If not given, default values are used for image export). The file should be of the following format -

      +

      {

      +
      +

      “data_name”: “elevation”,

      +

      ”sampling_resolution”: [

      +
      +
      +

      150,

      +

      150

      +
      +

      ],

      +
      +

      ”projection”: “3031”,

      +
      +

      }

      +

      Where data_name (string) is the name of the mesh data that will be included in the tif image (ex. SIC, elevation), if it is a vector data (e.g. fuel) then the vector mean is calculated for each pixel, +sampling_resolution ([int]) is a 2d array that represents the sampling resolution the geotiff will be generated at (how many pixels in the final image), +projection (int) is an int representing the ESPG sampling projection used to create the geotiff image (default is 4326), +and colour_conf (string) contains the path to color config file, which is a text-based file containing the association between data_name values and colors. It contains 4 columns per line: the data_name value and the corresponding red, green, blue value between 0 and 255, an example format where values range from 0 to 100 is -

      +
      +

      0 240 250 160

      +

      30 230 220 170

      +

      60 220 220 220

      +

      100 250 250 250

      +
      +

    • +
    • path (string) – the path to save the generated tif image.

    • +
    +
    +
    +
    + +
    +
    +update_cellbox(index, values)
    +

    method that adds values to the dict of a cellbox at certain index (to be used by the vessel perf. module to add the perf. metrics to the cellbox)

    +
    +
    Parameters:
    +
      +
    • index (int) – the index of the cellbox to be updated

    • +
    • values (dict) – a dict contains perf. metrics names and values

    • +
    +
    +
    +
    + +
    + +
    +
    +

    8.4.1.3. NeighbourGraph

    +

    The NeighbourGraph object is used to store the connectivity information between the cells of the EnvironmentMesh. +The NeighbourGraph object is created by the MeshBuilder object and is encoded into the EnvironmentalMesh.

    +
    +
    +class meshiphi.mesh_generation.neighbour_graph.NeighbourGraph(cellboxes=None, grid_width=0)
    +

    A NeighbourGraph is a class that defines the graphical representation of the adjacency relationship between CellBoxes in the Mesh.

    +
    +
    +neighbour_graph
    +

    a dictionary that contains cellboxes ids along with their adjacent neighbours in the following form

    +

    {

    +
    +

    <CellBox id_1>: {

    +
    +

    “1”: [id_1,…,id_n],

    +

    “2”: [id_1,…,id_n],

    +

    “3”: [id_1,…,id_n],

    +

    “4”: [id_1,…,id_n],

    +

    “-1”: [id_1,…,id_n],

    +

    “-2”: [id_1,…,id_n],

    +

    “-3”: [id_1,…,id_n],

    +

    “-4”: [id_1,…,id_n],

    +
    +

    },

    +

    …,

    +

    {

    +
    +

    <CellBox id_n>: {

    +
    +

    +
    +

    }

    +
    +

    }

    +
    +

    }

    +
    +
    Type:
    +

    dict

    +
    +
    +
    + +
    +
    +get_neighbour_case(cellbox_a, cellbox_b)
    +

    Given two cellboxes (cellbox_a, cellbox_b) returns a case number +representing where the two cellboxes are touching.

    +
    +
    Parameters:
    +
      +
    • cellbox_a (CellBox) – starting CellBox

    • +
    • cellbox_b (CellBox) – destination CellBox

    • +
    +
    +
    Returns:
    +

    an int representing the direction of the adjacency between input cellbox_a and cellbox_b. The meaning of each case is as follows -

    +
    +

    case 0 -> CellBoxes are not neighbours

    +

    case 1 -> cellbox_b is the North-East corner of cellbox_a

    +

    case 2 -> cellbox_b is East of cellbox_a

    +

    case 3 -> cellbox_b is the South-East corner of cellbox_a

    +

    case 4 -> cellbox_b is South of cellbox_a

    +

    case -1 -> cellbox_b is the South-West corner of cellbox_a

    +

    case -2 -> cellbox_b is West of cellbox_a

    +

    case -3 -> cellbox_b is the North-West corner of cellbox_a

    +

    case -4 -> cellbox_b is North of cellbox_a

    +
    +

    +
    +
    Return type:
    +

    int

    +
    +
    +
    + +
    +
    +initialise_neighbour_graph(cellboxes, grid_width)
    +

    initialize the neighbour graph

    +
    + +
    +
    +update_neighbours(cellbox_indx, new_neighbours_indx, direction, cellboxes)
    +

    method that updates the neighbour of a certain cellbox in a specific direction. It removes cellbox_indx from the neighbour_map of its neighbours in a specific direction and add new_neighbour_indx

    +
    +
    Parameters:
    +
      +
    • cellbox_index (int) – index of the cellbox that its neighbour will be updated

    • +
    • new_neighbour_indx (int) – the index of the new neighbour that will replace cellbox_index

    • +
    • direction (int) – an int that represents the direction of the neighbours that will get updated (e.g. north, south ,..)

    • +
    • cellboxes (list<CellBox>) – the list that contains all the cellboxes of the mesh

    • +
    +
    +
    +
    + +
    + +
    +
    +

    8.4.1.4. CellBox

    +

    The CellBox object is used to store the data contained within a geospatial boundary in the MeshBuilder. +The CellBox object is created by the MeshBuilder object and transformed into an AggregatedCellBox object +when the MeshBuilder returns the EnvironmentalMesh object.

    +

    Outlined in this section we will discuss the usage of the CellBox functionality of the meshiphi package. +In this series of class distributions we house our discrete representation of input data. In each CellBox, +we represent a way of accessing the information governing our numerical world, +this includes and is not limited to: Ocean Currents, Sea Ice Concentration and Bathymetric depth.

    +
    +

    Example:

    +

    An example of running this code can be executed by running the following in a ipython/Jupyter Notebook:

    +
    from meshiphi.mesh_generation.cellbox import cellbox
    +
    +....
    +
    +
    +

    Note:

    +
    +
    +
    CellBoxes are intended to be constructed by and used within a Mesh object.

    The methods provided are to extract information for CellBoxes contained within a Mesh.

    +
    +
    +
    +
    +
    +
    +class meshiphi.mesh_generation.cellbox.CellBox(bounds, id)
    +

    A CellBox represnts a geo-spatial/temporal boundary that enables projecting to information within. +Information about any given value of a CellBox is calculated from aggregating all data points of within those bounds. +CellBoxes may be split into smaller CellBoxes and the data points within distributed between the newly created +CellBoxes so as to construct a non-uniform mesh of CellBoxes, such as within a Mesh.

    +
    +
    +Bounds
    +

    object that contains the latitude and logtitute range and the time range

    +
    +
    Type:
    +

    Boundary

    +
    +
    +
    + +
    +
    +id
    +

    the id of the cellbox

    +
    +
    Type:
    +

    int

    +
    +
    +
    + +
    +
    +__init__(bounds, id)
    +
    +
    Parameters:
    +
      +
    • bounds (Boundary) – encapsulates latitude, longtitude and time range of the CellBox

    • +
    • id (int) – the id of the cellbox

    • +
    +
    +
    +
    + +
    +
    +aggregate()
    +

    aggregates CellBox data using the associated data_sources’ aggregate type (ex. MEAN, MAX) +and returns AggregatedCellBox object

    +
    +
    Returns:
    +

    object contains the aggregated data within cellbox bounds.

    +
    +
    Return type:
    +

    AggregatedCellbox

    +
    +
    +
    + +
    +
    +set_data_source(data_source)
    +
    +
    a method that sets the data source of the cellbox ( which includes the data loaders,

    splitting conditions and aggregation type)

    +
    +
    +
    +
    Parameters:
    +

    data_source (List <MetaData>) – a list of MetaData objects, each object represents a source of this CellBox data +(where the data comes from, how it is spitted and aggregated)

    +
    +
    +
    + +
    +
    +set_parent(parent)
    +

    set the parent CellBox, which is the bigger CellBox that conains this CellBox +:param CellBox: the bigger Cellbox object that got splitted to produce this cellbox

    +
    + +
    +
    +should_split(stop_index)
    +

    determines if a cellbox should be split based on the homogeneity +condition of each data type contained within. The homogeneity condition +of values within this cellbox is calculated using the method +‘get_hom_cond’ in each DataLoader object inside CellBox’s metadata

    +
    +
    if ANY data returns ‘HOM’:

    do not split

    +
    +
    if ANY data returns ‘MIN’:

    do not split

    +
    +
    if ALL data returns ‘CLR’:

    do not split

    +
    +
    else (mixture of CLR & HET):

    split

    +
    +
    +
    +
    Parameters:
    +
      +
    • stop_index – the index of the data source at which checking the splitting conditions stops.

    • +
    • splitting. (Implemented like this to perform depth-first) –

    • +
    • splitting (Should be deprecated once we switch to breadth-first) –

    • +
    +
    +
    Returns:
    +

    +
    True if the splitting_conditions of this CellBox

    will result in the CellBox being split.

    +
    +
    +

    +
    +
    Return type:
    +

    bool

    +
    +
    +
    + +
    +
    +split(start_id)
    +

    splits the current cellbox into 4 corners, returns as a list of cellbox objects.

    +
    +
    Parameters:
    +

    start_id – represenst the start of the splitted cellboxes ids, +usuallly it is the number of the existing cellboxes

    +
    +
    Returns:
    +

    The 4 corner cellboxes generated by splitting +the cellbox uniformly.

    +
    +
    Return type:
    +

    list<CellBox>

    +
    +
    +
    + +
    + +
    +
    +

    8.4.1.5. MetaData

    +

    The Metadata object is used to store the metadata associated with a CellBox object within the MeshBuilder. This includes +associated DataLoaders, the depth of the CellBox within the MeshBuilder, and the parent CellBox of the CellBox among others.

    +
    +
    +class meshiphi.mesh_generation.metadata.Metadata(data_loader, spliiting_conditions=None, value_fill_type='')
    +

    A Metadata is a class that defines the datasource for a certain Cellbox and the assocated splitting conditions.

    +
    +
    +data_loader
    +

    object of the DataLoader class that enable projecting to the cellbox data

    +
    + +
    +
    +splitting_conditions
    +

    list of conditions that determine how to split the data accessed by data_loader

    +
    + +
    +
    +value_fill_type
    +

    indicates how to fill a CellBox if it has void data +(ex. use the data in the parent cellbox or assign 0 to the data)

    +
    +
    Type:
    +

    string

    +
    +
    +
    + +
    +
    +__init__(data_loader, spliiting_conditions=None, value_fill_type='')
    +
    +
    Parameters:
    +
      +
    • data_loader (DataLoader) – object of the DataLoader class that enables projecting to the cellbox data

    • +
    • splitting_conditions (List<dict>) – list of conditions that determine how to split CellBox

    • +
    • value_fill_tyep (string) – represents the way the data of a cellbox will be filled +in case it has void data (ex. parent , 0 )

    • +
    +
    +
    +
    + +
    + +
    +
    +

    8.4.1.6. AggregatedCellBox

    +

    An aggregated representation of the data contained within a geospatial boundary. The AggregatedCellBox object is created +by the CellBox object when the MeshBuilder returns the EnvironmentalMesh.

    +
    +
    +class meshiphi.mesh_generation.aggregated_cellbox.AggregatedCellBox(boundary, agg_data, id)
    +

    a class represnts an aggrgated information within a geo-spatial/temporal boundary.

    +

    Attributes:

    +
    +

    Note

    +

    All geospatial boundaries of a CellBox are given in a ‘EPSG:4326’ projection

    +
    +
    +
    +__init__(boundary, agg_data, id)
    +
    +
    Parameters:
    +
      +
    • boundary (Boundary) – encapsulates latitude, longtitude and time range of the CellBox

    • +
    • agg_data (dict) – a dictionary that contains data_names and agg values

    • +
    • id (string) – a string represents cellbox id

    • +
    +
    +
    +
    + +
    +
    +contains_point(lat, long)
    +

    Returns true if a given lat/long coordinate is contained within this cellbox.

    +
    +
    Parameters:
    +
      +
    • lat (float) – latitude of a given point

    • +
    • long (float) – longitude of a given point

    • +
    +
    +
    Returns:
    +

    +
    True if this CellBox contains a point given by

    parameters (lat, long)

    +
    +
    +

    +
    +
    Return type:
    +

    contains_points (bool)

    +
    +
    +
    + +
    +
    +to_json()
    +

    convert cellbox to JSON

    +

    The returned object is of the form -

    +
    +

    {

    +
    +

    “geometry” (String): POLYGON(…),

    +

    “cx” (float): …,

    +

    “cy” (float): …,

    +

    “dcx” (float): …,

    +

    “dcy” (float): …,

    +

    “agg_value_1” (float): …,

    +

    …,

    +

    “agg_value_n” (float): …

    +
    +

    }

    +
    +
    +
    Returns:
    +

    A JSON parsable dictionary representation of this AggregatedCellBox

    +
    +
    Return type:
    +

    cell_json (dict)

    +
    +
    +
    + +
    + +
    +
    + + +
    +
    + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/docs/html/sections/Mesh_Construction/Mesh_construction_overview.html b/docs/html/sections/Mesh_Construction/Mesh_construction_overview.html new file mode 100644 index 00000000..14cb3403 --- /dev/null +++ b/docs/html/sections/Mesh_Construction/Mesh_construction_overview.html @@ -0,0 +1,175 @@ + + + + + + + 8. Methods - Mesh Construction — meshiphi 1.1.5 documentation + + + + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    + +
    +
    +
    +
    + +
    +

    8. Methods - Mesh Construction

    +

    Throughout this section we will outline an overview of the Environment Mesh Construction +module, describe the main classes that composes the module and illustrate a use case for +the Discrete Meshing of the environment.

    +
    +

    8.1. Mesh Construction - Overview

    +

    A general overview of the method can be seen below:

    +
    +../../_images/FlowDiagram_MeshGraph.png +
    +

    Overview figure of the Discrete Meshing from the multi-data input.

    +
    +
    +
    +
    +

    8.2. Mesh Construction Design

    +

    The below UML diagram describes how the Environment Mesh Construction module is designed. +It depicts the classes of the module and how they interact with each other.

    +
    +../../_images/mesh-construct-UML.drawio.png +
    +
    +
    +

    8.3. Mesh Construction Use case

    +

    This sequence diagram illustrates a use case for the Discrete Meshing of the environment, +where the module’s client starts by initializing the MeshBuilder with a certain mesh +configuration (see Input-Configuration section for more details about the configuration format) +then calls build_environment_mesh method.

    +
    +../../_images/mesh-build-sequence-diagram.drawio.png +
    +

    The following diagram depicts the sequence of events that take place inside build_environment_mesh +method into details

    +
    +../../_images/build-env-mesh.drawio.png +
    +

    For a more in-depth explanation of the mesh construction methods, please refer to the Mesh Construction - Classes +section.

    +
    +
    +

    8.4. Mesh Construction - Additional

    + +
    +
    + + +
    +
    + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/docs/html/sections/Mesh_Construction/Mesh_validation.html b/docs/html/sections/Mesh_Construction/Mesh_validation.html new file mode 100644 index 00000000..2cfec784 --- /dev/null +++ b/docs/html/sections/Mesh_Construction/Mesh_validation.html @@ -0,0 +1,295 @@ + + + + + + + 8.4.2. Mesh Validation — meshiphi 1.1.5 documentation + + + + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    + +
    +
    +
    +
    + +
    +

    8.4.2. Mesh Validation

    +

    TODO - add description

    +
    +

    8.4.2.1. Mesh Validator

    +
    +
    +class meshiphi.mesh_validation.mesh_validator.MeshValidator(mesh_config_file)
    +

    a class that validates a constructed mesh against its actual sourced geo-spatial data. Validation takes place by comparing the aggregated data value of mesh’s cellbox against the actual data contained within cellbox’s bounds. +.. attribute:: conf

    +
    +

    conatins the initial config used to build the mesh under vlaidation

    +
    +
    type:
    +

    dict

    +
    +
    +
    +
    +
    +validation_length
    +

    the legnth of the validation square used for each sample, all the data_points contained within this square wil be validated. Higher values would incur higher processing cost

    +
    +
    Type:
    +

    float

    +
    +
    +
    + +
    +
    +mesh
    +

    object that represents the constructed mesh (a representation before aggregating cellbox data, used to have access to the mesh data source to validate against the actual data)

    +
    +
    Type:
    +

    Mesh

    +
    +
    +
    + +
    +
    +env_mesh
    +

    objects that represents the constructed env mesh (a representation after aggregating the mesh cellboox data)

    +
    +
    Type:
    +

    EnvironmentMesh

    +
    +
    +
    + +
    +
    +__init__(mesh_config_file)
    +
    +
    Parameters:
    +

    mesh_config_file (String) – the path to the config file used to build the mesh under validation

    +
    +
    +
    + +
    +
    +get_range_end(sample)
    +

    calculates the range end of the provided sample lat and long, claculation is based on the specified validation_length +:param sample: a decimal array contains the sampled lat and long values +:type sample: float[]

    +
    +
    Returns:
    +

    lat and long range end

    +
    +
    Return type:
    +

    float[]

    +
    +
    +
    + +
    +
    +get_value_from_data(sample)
    +

    gets the actual data within the provided sample lat and long +:param sample: a decimal array contains the sampled lat and long values +:type sample: float[]

    +
    +
    Returns:
    +

    a numpy array that contains all the data within the sampled lat and long range

    +
    +
    +
    + +
    +
    +get_values_from_mesh(sample)
    +

    finds the mesh’s cellboxes that contains the sample’s lat and long then returns the aggregated values within. +Args: +sample (float[]): a decimal array contains the sampled lat and long values +:returns: a numpy array that contains the mesh’s data within the sampled lat and long range

    +
    + +
    +
    +validate_mesh(number_of_samples=10)
    +

    samples the mesh’s lat and long space and compares the actual data within the sampled’s range to the mesh agg_value then calculates the RMSE.

    +
    +
    +
    Args:

    number_of_samples (int): the number of samples used to validate the mesh

    +
    +
    Returns:

    distance (float): the RMSE between the actaul data value and the mesh’s agg_value.

    +
    +
    +
    +
    + +
    + +
    +
    +

    8.4.2.2. Sampler

    +
    +
    +class meshiphi.mesh_validation.sampler.Sampler(d, n)
    +

    a class that generates samples based on Sobol sequences, which fills the space in a highly uniform way and guarantees a better coverage of the sampling space. +.. attribute:: dimensions

    +
    +

    an integer representing the dimensions of each sample

    +
    +
    type:
    +

    int

    +
    +
    +
    +
    +
    +number_of_samples
    +

    an integer representing the number of the generated samples

    +
    +
    Type:
    +

    int

    +
    +
    +
    + +
    +
    +__init__(d, n)
    +
    + +
    +
    +generate_samples(ranges)
    +

    generates samples within the provided ranges array, the length of the ranges should equal to self.dimensions

    +
    +
    +
    Args:

    ranges (float[]): an array that contains the range that each sample dimension should fall within

    +
    +
    Returns:

    distance (float): the RMSE between the actaul data value and the mesh’s agg_value.

    +
    +
    +
    +
    + +
    + +
    +
    + + +
    +
    + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/docs/html/sections/Plotting/mesh_plotting.html b/docs/html/sections/Plotting/mesh_plotting.html new file mode 100644 index 00000000..d84a299b --- /dev/null +++ b/docs/html/sections/Plotting/mesh_plotting.html @@ -0,0 +1,116 @@ + + + + + + + 9. Mesh Plotting — meshiphi 1.1.5 documentation + + + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    + +
    +
    +
    +
    + +
    +

    9. Mesh Plotting

    +
    + + +
    +
    + +
    +
    +
    +
    + + + + \ No newline at end of file diff --git a/docs/html/sections/ipython_notebooks.html b/docs/html/sections/ipython_notebooks.html new file mode 100644 index 00000000..fe77d24c --- /dev/null +++ b/docs/html/sections/ipython_notebooks.html @@ -0,0 +1,175 @@ + + + + + + + 2. Examples — meshiphi 1.1.5 documentation + + + + + + + + + + + + + + + + + + + +
    + + +
    + +
    +
    +
    + +
    +
    +
    +
    + +
    +

    2. Examples

    +

    Digital environement files (meshes) can be created using the MeshiPhi package, either through the +command line interface (CLI) or through the python terminal. This section will provide examples of how to create a digital +environement file using the python terminal.

    +
    +

    2.1. Creating the digital environment.

    +

    A configuration file is needed to initialise the `Mesh` object which forms the digital environment. This configuration file +is of the same format used in the create_mesh CLI entry-point, and may either be loaded from a json file or constructed +within the python terminal.

    +

    Loading configuration from json file:

    +
    import json
    +with open('examples/environment_config/grf_example.config.json', 'r') as f:
    +    config = json.load(f)
    +
    +
    +

    The digital environment `Mesh` object can then be initialised. This mesh object will be constructed using parameters in it +configuration file. This mesh object can be manipulated further, such as increasing its resolution through further +splitting, adding additional data sources or altering is configuration parameters using functions listed in +the Methods - Mesh Construction section of the documentation. The digital environment `Mesh` object can then be cast to +a json object and saved to a file.

    +
    from meshiphi.mesh_generation.mesh_builder import MeshBuilder
    +
    +cg = MeshBuilder(config).build_environmental_mesh()
    +
    +mesh = cg.to_json()
    +
    +
    +

    The `Mesh` object can be visualised using the `GeoPlot` package, also developed by BAS. This package is not included in the distribution +of MeshiPhi, but can be installed using the following command:

    +
    pip install bas_geoplot
    +
    +
    +

    `GeoPlot` can be used to visualise the `Mesh` object using the following code in an iPython notebook:

    +
    from bas_geoplot.interactive import Map
    +
    +mesh = pd.DataFrame(mesh_json['cellboxes'])
    +mp = Map(title="GRF Example")
    +
    +mp.Maps(mesh, 'MeshGrid', predefined='cx')
    +mp.Maps(mesh, 'SIC', predefined='SIC')
    +mp.Maps(mesh, 'Elevation', predefined='Elev', show=False)
    +mp.Vectors(mesh,'Currents - Mesh', show=False, predefined='Currents')
    +mp.Vectors(mesh, 'Winds', predefined='Winds', show=False)
    +
    +mp.show()
    +
    +
    +

    The prior should produce a plot which shows the digital environment, including sea ice concentration, elevation, currents and winds.

    +
    +../_images/grf_example_mesh.png +
    +

    plot showing expected output of running bas_geoplot though a ipython notebook

    +
    +
    +
    +
    + + +
    +
    + +
    +
    +
    +
    + + + + \ No newline at end of file From 0f38a48d7952a1ee41f1385e071e69582bc61ec0 Mon Sep 17 00:00:00 2001 From: George Date: Fri, 16 Feb 2024 15:26:18 +0000 Subject: [PATCH 33/39] Remove unnecessary old files --- docs/html/sections/Examples.html | 134 ----- docs/html/sections/Route_optimisation.html | 571 -------------------- docs/html/sections/Vehicle_specifics.html | 488 ----------------- docs/source/sections/example_routepath.html | 4 - 4 files changed, 1197 deletions(-) delete mode 100644 docs/html/sections/Examples.html delete mode 100644 docs/html/sections/Route_optimisation.html delete mode 100644 docs/html/sections/Vehicle_specifics.html delete mode 100644 docs/source/sections/example_routepath.html diff --git a/docs/html/sections/Examples.html b/docs/html/sections/Examples.html deleted file mode 100644 index ce6fdc36..00000000 --- a/docs/html/sections/Examples.html +++ /dev/null @@ -1,134 +0,0 @@ - - - - - - - 9. Examples of running code — meshiphi 1.1.5 documentation - - - - - - - - - - - - - - - - - - -
    - - -
    - -
    -
    -
    - -
    -
    -
    -
    - -
    -

    9. Examples of running code

    -

    Throughout this section we will discuss a series of examples that can be run by the user either from the Command-Line or within python/ipython notebooks. All these examples and more can be found at the Google Colab Link.

    -
    -

    9.1. Example 1 - Antarctica Processing all stages of route planner

    -

    In this section we will outline the full processing procedures for running PolarRoute …to be added shortly …

    -
    -
    -

    9.2. Example 2 - Dijkstra vs smooth paths

    -

    …to be added shortly …

    -
    -
    -

    9.3. Example 2 - Variations of Vehicle Properties on Route Paths

    -

    …to be added shortly …

    -
    -
    - - -
    -
    - -
    -
    -
    -
    - - - - \ No newline at end of file diff --git a/docs/html/sections/Route_optimisation.html b/docs/html/sections/Route_optimisation.html deleted file mode 100644 index bc4aca0d..00000000 --- a/docs/html/sections/Route_optimisation.html +++ /dev/null @@ -1,571 +0,0 @@ - - - - - - - 10. Methods - Route Planner — polar_route 0.3.0 documentation - - - - - - - - - - - - - - - - -
    - - -
    - -
    -
    -
    - -
    -
    -
    -
    - -
    -

    10. Methods - Route Planner

    -
    -

    10.1. Route Optimisation Overview

    -

    In this section we outline the code used to generate optimal routes through a mesh constructed by the methods described -in previous sections. This mesh should include the vessel performance parameters with respect to which objective -functions can be defined for optimisation.

    -
    -
    -

    10.2. Route Optimisation Modules

    -
    -

    10.2.1. Route Planner

    -

    This section of the codebase is used for construction of route paths using the -environmental mesh between a series of user defined waypoints

    -
    -
    -class polar_route.route_planner.RoutePlanner(mesh, config, waypoints, cost_func=<class 'polar_route.crossing.NewtonianDistance'>)
    -

    -

    RoutePlanner optimises the route paths between a series of waypoints. -The routes are constructed in a two stage process:

    -
    -
    compute_routes: uses a mesh based Dijkstra method to determine the optimal routes

    between a series of waypoint.

    -
    -
    compute_smoothed_routes: smooths the compute_routes using information from the environmental mesh

    to determine mesh independent optimal route paths

    -
    -
    -

    -
    -
    -waypoints
    -
    -
    A dictionary of the waypoints supplied by the user in the region

    of interest. The waypoints are of the form:

    -
    -
    -

    {

    -
    -

    “Name”:{

    -
    -

    ‘0’:”Falklands”,

    -

    ‘1’:”Rothera”,

    -

    -
    -

    },

    -

    “Lat”:{

    -
    -

    ‘0’:-52.6347222222, -‘1’:-75.26722,

    -

    -
    -

    },

    -

    “Long”:{

    -
    -

    -
    -

    },

    -

    “index”:{

    -
    -

    -
    -

    }

    -
    -

    }

    -
    -
    Type:
    -

    dict

    -
    -
    -
    - -
    -
    -paths
    -

    A GeoJSON of all paths constructed. The paths are in the form:

    -

    {

    -
    -

    ‘types’:’FeatureCollection’,

    -

    “features”:{[

    -
    -

    ‘type’:’feature’,

    -

    ‘geometry’:{

    -
    -

    ‘type’: ‘LineString’,

    -

    ‘coordinates’: [[-27.21694, -75.26722],

    -
    -

    [-27.5, -75.07960297382266],

    -

    [-27.619238882768894, -75.0],

    -

    …]

    -
    -
    -

    }, -‘properties’:{

    -
    -

    ‘from’: ‘Halley’,

    -

    ‘to’: ‘Rothera’,

    -

    ‘traveltime’: [0.0,

    -
    -

    0.03531938671648596,

    -

    0.050310986633880575,

    -

    …],

    -
    -

    ‘fuel’: [0.0,

    -
    -

    0.9648858923588642,

    -

    1.3745886107069096,

    -

    …],

    -
    -
    -
    ‘times’: [‘2017-01-01 00:00:00’,

    ‘2017-01-01 00:50:51.595036800’, -‘2017-01-01 01:12:26.869276800’, -…]

    -
    -
    -
    -

    }

    -
    -

    ]}

    -
    -

    }

    -
    -
    Type:
    -

    geojson

    -
    -
    -
    - -

    -
    -
    -_dijkstra(wpt_name)
    -

    Runs dijkstra across the whole of the domain.

    -
    - -
    -
    -_dijkstra_paths(start_waypoints, end_waypoints)
    -

    Hidden function. Given internal variables and start and end waypoints this function -returns a GEOJSON formatted path dict object

    -
    -
    INPUTS:

    start_waypoints: Start waypoint names (list) -end_waypoints: End waypoint names (list)

    -
    -
    -
    - -
    -
    -_neighbour_cost(wpt_name, minimum_objective_index)
    -

    Determines the neighbour cost from a source cellbox to all of its neighbours. -These are then used to update the edge values in the dijkstra graph.

    -
    - -
    -
    -_objective_value(variable, source_graph, neighbour_graph, traveltime, case)
    -

    Hidden variable. Returns the objective value between two cellboxes.

    -
    - -
    -
    -compute_routes()
    -

    Computes the Dijkstra Paths between waypoints. -waypoints and paths are appended to output JSON

    -
    - -
    -
    -compute_smoothed_routes(blocked_metric='SIC', debugging=False)
    -

    Using the previously constructed Dijkstra paths smooth the paths to remove mesh features -paths will be updated in the output JSON

    -
    - -
    -
    -to_json()
    -

    Outputting the information in JSON format

    -
    - -
    - -
    -
    -polar_route.route_planner._initialise_dijkstra_graph(dijkstra_graph)
    -

    Initialising dijkstra graph information in a standard form

    -
    -
    Parameters:
    -

    dijkstra_graph (pd.dataframe) –

    -
    -
    -
    -
    Outputs:
    -
    dijkstra_graph_dict (dict) - Dictionary comprising dijkstra graph with keys based on cellbox id.

    Each entry is a dictionary of the cellbox environmental and dijkstra information.

    -
    -
    -
    -
    -
    - -
    -
    -polar_route.route_planner._initialise_dijkstra_route(dijkstra_graph, dijkstra_route)
    -

    Initialising dijkstra route info a standard path form

    -
    -
    Parameters:
    -
      -
    • dijkstra_graph (dict) – Each entry is a dictionary of the cellbox environmental and dijkstra information.

    • -
    • dijkstra_route (dict) –

    • -
    -
    -
    -
    -
    Outputs:
    -
    aps (list, [find_edge, …]) - A list of adjacent cell pairs where each entry is of type find_edge including information on

    .crossing, .case, .start, and .end see ‘find_edge’ for more information

    -
    -
    -
    -
    -
    - -
    -
    -polar_route.route_planner._json_str(input)
    -

    Load JSON object either from dict or from file

    -
    -
    Input:

    input (dict or string) - JSON file/dict

    -
    -
    Output:

    output (dict) - Dictionary from JSON object

    -
    -
    -
    - -
    -
    -

    10.2.2. Crossing Points

    -

    The python package crossing implement the optimisation for the crossing point for the unsmoothed and smoothed path -construction. The package is separated into two classes NewtonianDistance and NewtonianCurve. -In the section below we will go through, stage by stage, how the crossing point is determined and the methods -used within the classes.

    -
    -
    -

    10.2.3. Crossing Point Smoothing

    -
    -
    -class polar_route.crossing_smoothing.PathValues
    -

    A class that returns attributes along a given paths intersecting the environmental/vessel mesh.

    -
    -
    -path_requested_variables
    -
    -
    e.g.{‘distance’:{‘processing’:’cumsum’},

    ‘traveltime’:{‘processing’:’cumsum’}, -‘datetime’:{‘processing’:’cumsum’}, -‘cell_index’:{‘processing’:None}, -‘fuel’:{‘processing’:’cumsum’}}

    -
    -
    -
    -
    Type:
    -

    dict

    -
    -
    -
    - -
    -
    -unit_shipspeed
    -

    ‘km/hr’,’knots’

    -
    -
    Type:
    -

    string

    -
    -
    -
    - -
    -
    -unit_time
    -

    ‘days’,’hr’,’min’,’s

    -
    -
    Type:
    -

    string

    -
    -
    -
    - -
    -
    Functions:

    objective_function - For a list of adjacent cell pairs, start and end waypoints compute path attributes

    -
    -
    -
    -
    -_case_from_angle(start, end)
    -

    Determine the direction of travel between two points in the same cell and return the associated case

    -
    -
    Parameters:
    -
      -
    • start (list) – the coordinates of the start point within the cell

    • -
    • end (list) – the coordinates of the end point within the cell

    • -
    -
    -
    Returns:
    -

    the case to use to select variable values from a list

    -
    -
    Return type:
    -

    case (int)

    -
    -
    -
    - -
    -
    -_traveltime_in_cell(xdist, ydist, U, V, S)
    -

    Determine the traveltime within cell

    -
    -
    Inputs:

    xdist (float) - Longitude distance between two points in km -ydist (float) - Latitude distance between two points in km -U (float) - U-Component for the forcing vector -V (float) - V-Component for the forcing vector -S (float) - Speed of the vehicle

    -
    -
    -
    - -
    -
    -_unit_speed(Val)
    -

    Applying unit speed for an input type.

    -
    -
    Input:

    Val (float) - Input speed in m/s

    -
    -
    Output:

    Val (float) - Output speed in unit type unit_shipspeed

    -
    -
    -
    - -
    -
    -_unit_time(Val)
    -

    Applying unit time for an input type.

    -
    -
    Input:

    Val (float) - Input time in s

    -
    -
    Output:

    Val (float) - Output time in unit type unit_time

    -
    -
    -
    - -
    -
    -_waypoint_correction(path_requested_variables, source_graph, Wp, Cp)
    -

    Applies an in-cell correction to a path segments to determine ‘path_requested_variables’ -defined by the use (e.g. total distance, total traveltime, total fuel usage)

    -
    -
    Input:

    path_requested_variable (dict) - A dictionary of the path requested variables -source_graph (dict) - Dictionary of the cell in which the vessel is transiting -Wp (tuple) - Start Waypoint location (long,lat) -Cp (tuple) - End Waypoint location (long,lat)

    -
    -
    -
    -
    Returns:
    -

    segment_values (dict) - Dictionary of the segment value information -case (int) - Adjacency case type connecting the two points

    -
    -
    -
    - -
    -
    -objective_function(adjacent_pairs, start_waypoint, end_waypoint)
    -

    Given a list of adjacent pairs determine the path related information -apply waypoint_correction to get path related information along the path

    -
    -
    Inputs:

    adjacent_pairs (list of type find_edge) - A list of the adjacent cell pairs in the form of find_edge -start_waypoint (tuple) - Start waypoint (long,lat) -end_waypoint (tuple) - End waypoint (long,lat)

    -
    -
    -
    - -
    - -
    -
    -polar_route.crossing_smoothing._dist_around_globe(start_point, crossing_point)
    -

    Determining the longitude distance around the globe between two points

    -
    -
    Parameters:
    -
      -
    • start_point (tuple) – Start Waypoint (long,lat)

    • -
    • crossing_point (tuple) – End Waypoint (long,lat)

    • -
    -
    -
    Returns:
    -

    longitude distance between the two points in degrees

    -
    -
    Return type:
    -

    a (float)

    -
    -
    -
    - -
    -
    -class polar_route.crossing_smoothing.find_edge(cell_a, cell_b, case)
    -

    Class to return characteristics information about the edge connecting two -cells. This information includes.

    -

    crossing (tuple) - Crossing point (long,lat) -case (int) - Case type connecting the two cells -start (dict) - Dictionary containing the environmental parameters of the start cell -end (dict) - Dictionary containing the environmental parameters of the end cell

    -
    -
    -_find_edge(cell_a, cell_b, case)
    -

    Function that returns the edge connecting to cells, cell_a and cell_b. If there is no edge -connecting the two then it returns None

    -
    -
    Parameters:
    -
      -
    • cell_a (dict) – Dictionary of cell_a information

    • -
    • cell_b (dict) – Dictionary of cell_b information

    • -
    -
    -
    -
    -
    Returns

    crossing (tuple) - Crossing point (long,lat) connecting the two cells -case (int) - Case type connecting the two cells -start (dict) - Dictionary containing the environmental parameters of the start cell -end (dict) - Dictionary containing the environmental parameters of the end cell

    -
    -
    -
    - -
    - -
    -
    -
    - - -
    -
    - -
    -
    -
    -
    - - - - \ No newline at end of file diff --git a/docs/html/sections/Vehicle_specifics.html b/docs/html/sections/Vehicle_specifics.html deleted file mode 100644 index 07ea2c5a..00000000 --- a/docs/html/sections/Vehicle_specifics.html +++ /dev/null @@ -1,488 +0,0 @@ - - - - - - - 9. Methods - Vessel Performance — polar_route 0.3.0 documentation - - - - - - - - - - - - - - - - -
    - - -
    - -
    -
    -
    - -
    -
    -
    -
    - -
    -

    9. Methods - Vessel Performance

    -
    -

    9.1. Vessel Overview

    -

    All of the functionality that relates to the specific vehicle traversing our meshed environment model is contained within the vessel_performance directory. -This directory contains a VesselPerformanceModeller class that initialises one of the vessel classes in vessels and uses this to determine which cells -in a given mesh are inaccessible for that particular vessel and what its performance will be in each of the accessible cells.

    -
    -../_images/Mesh_Fuel_Speed.jpg -
    -

    Maps of the sea ice concentration (a), speed (b) and fuel consumption (c) across the Weddell Sea. -The latter two quantities are derived from the former.

    -
    -
    -
    -../_images/VesselUML.png -
    -

    UML Diagram detailing the vessel performance subsystem

    -
    -
    -
    -
    -

    9.2. Vessel Performance Modeller

    -
    -
    -class polar_route.vessel_performance.vessel_performance_modeller.VesselPerformanceModeller(env_mesh_json, vessel_config)
    -

    Class for modelling the vessel performance. -Takes both an environmental mesh and vessel config as input in json format and modifies the input mesh to -include vessel specifics.

    -
    -
    -__init__(env_mesh_json, vessel_config)
    -
    -
    Parameters:
    -
      -
    • env_mesh_json (dict) – a dictionary loaded from an environmental mesh json file

    • -
    • vessel_config (dict) – a dictionary loaded from a vessel config json file

    • -
    -
    -
    -
    - -
    -
    -model_accessibility()
    -

    Method to determine the accessibility of cells in the environmental mesh and remove inaccessible cells from the -neighbour graph.

    -
    - -
    -
    -model_performance()
    -

    Method to calculate the relevant vessel performance values for each cell in the environmental mesh and update -the mesh accordingly.

    -
    - -
    -
    -to_json()
    -

    Method to return the modified mesh in json format.

    -
    -
    Returns:
    -

    a dictionary representation of the modified mesh.

    -
    -
    Return type:
    -

    j_mesh (dict)

    -
    -
    -
    - -
    - -
    -
    -

    9.3. Vessel Factory

    -
    -
    -class polar_route.vessel_performance.vessel_factory.VesselFactory
    -

    Factory class to produce initialised vessel objects.

    -
    -
    -classmethod get_vessel(config)
    -

    Method to return an initialised instance of a vessel class designed for performance modelling -:param config: a vessel config dictionary -:type config: dict

    -
    -
    Returns:
    -

    an instance of a vessel class designed for performance modelling

    -
    -
    Return type:
    -

    vessel

    -
    -
    -
    - -
    - -
    -
    -

    9.4. Abstract Vessel

    -
    -
    -class polar_route.vessel_performance.abstract_vessel.AbstractVessel(params: dict)
    -

    Interface to define the abstract methods required for any vessel class to work within the VesselPerformanceModeller.

    -
    -
    -abstract __init__(params: dict)
    -

    Initialise the vessel object with parameters from the config. -:param params: vessel parameters from the vessel config file -:type params: dict

    -
    - -
    -
    -abstract model_accessibility(cellbox: AggregatedCellBox)
    -

    Determine accessibility of the input cell for the given vessel. -:param cellbox: cell in which accessibility is being determined -:type cellbox: AggregatedCellBox

    -
    -
    Returns:
    -

    values for the accessibility and other related booleans

    -
    -
    Return type:
    -

    access_values (dict)

    -
    -
    -
    - -
    -
    -abstract model_performance(cellbox: AggregatedCellBox)
    -

    Calculate performance parameters for the given vessel. -:param cellbox: cell in which performance is being modelled -:type cellbox: AggregatedCellBox

    -
    -
    Returns:
    -

    values for relevant performance parameters

    -
    -
    Return type:
    -

    performance_values (dict)

    -
    -
    -
    - -
    - -
    -
    -

    9.5. Abstract Ship

    -
    -
    -class polar_route.vessel_performance.vessels.abstract_ship.AbstractShip(params)
    -

    Abstract class to define the methods and attributes common to any vessel that is a ship

    -
    -
    -__init__(params)
    -
    -
    Parameters:
    -

    params (dict) – vessel parameters from the vessel config file

    -
    -
    -
    - -
    -
    -extreme_ice(cellbox)
    -

    Method to determine if a cell is inaccessible based on configured max ice concentration. -:param cellbox: input cell from environmental mesh -:type cellbox: AggregatedCellBox

    -
    -
    Returns:
    -

    boolean that is True if the cell is inaccessible due to ice

    -
    -
    Return type:
    -

    ext_ice (bool)

    -
    -
    -
    - -
    -
    -land(cellbox)
    -

    Method to determine if a cell is land based on configured minimum depth. -:param cellbox: input cell from environmental mesh -:type cellbox: AggregatedCellBox

    -
    -
    Returns:
    -

    boolean that is True if the cell is inaccessible due to land

    -
    -
    Return type:
    -

    land (bool)

    -
    -
    -
    - -
    -
    -model_accessibility(cellbox)
    -

    Method to determine if a given cell is accessible to the ship -:param cellbox: input cell from environmental mesh -:type cellbox: AggregatedCellBox

    -
    -
    Returns:
    -

    boolean values for the modelled accessibility criteria

    -
    -
    Return type:
    -

    access_values (dict)

    -
    -
    -
    - -
    -
    -model_performance(cellbox)
    -

    Method to determine the performance characteristics for the ship -:param cellbox: input cell from environmental mesh -:type cellbox: AggregatedCellBox

    -
    -
    Returns:
    -

    the value of the modelled performance characteristics for the ship

    -
    -
    Return type:
    -

    performance_values (dict)

    -
    -
    -
    - -
    - -
    -
    -

    9.6. SDA

    -
    -
    -class polar_route.vessel_performance.vessels.SDA.SDA(params)
    -

    Vessel class with methods specifically designed to model the performance of the British Antarctic Survey -research and supply ship, the RRS Sir David Attenborough (SDA)

    -
    -
    -__init__(params)
    -
    -
    Parameters:
    -

    params (dict) – vessel parameters from the vessel config file

    -
    -
    -
    - -
    -
    -invert_resistance(cellbox)
    -

    Method to find the vessel speed that keeps the ice resistance force below a given threshold in a given cell. -The input cellbox should contain the following values

    -
    -

    sic (float) - The average sea ice concentration in the cell as a percentage

    -

    thickness (float) - The average ice thickness in the cell in m

    -

    density (float) - The average ice density in the cell in kg/m^3

    -
    -
    -
    Parameters:
    -

    cellbox (AggregatedCellBox) – input cell from environmental mesh

    -
    -
    Returns:
    -

    Safe vessel speed in km/h

    -
    -
    Return type:
    -

    new_speed (float)

    -
    -
    -
    - -
    -
    -model_fuel(cellbox)
    -

    Method to determine the fuel consumption rate of the SDA in a given cell -:param cellbox: input cell from environmental mesh -:type cellbox: AggregatedCellBox

    -
    -
    Returns:
    -

    updated cell with fuel consumption values

    -
    -
    Return type:
    -

    cellbox (AggregatedCellBox)

    -
    -
    -
    - -
    -
    -model_resistance(cellbox)
    -

    Method to determine the resistance force acting on the SDA in a given cell -:param cellbox: input cell from environmental mesh -:type cellbox: AggregatedCellBox

    -
    -
    Returns:
    -

    updated cell with resistance values

    -
    -
    Return type:
    -

    cellbox (AggregatedCellBox)

    -
    -
    -
    - -
    -
    -model_speed(cellbox)
    -

    Method to determine the maximum speed that the SDA can traverse the given cell -:param cellbox: input cell from environmental mesh -:type cellbox: AggregatedCellBox

    -
    -
    Returns:
    -

    updated cell with speed values

    -
    -
    Return type:
    -

    cellbox (AggregatedCellBox)

    -
    -
    -
    - -
    - -
    -
    - - -
    -
    - -
    -
    -
    -
    - - - - \ No newline at end of file diff --git a/docs/source/sections/example_routepath.html b/docs/source/sections/example_routepath.html deleted file mode 100644 index 63065d89..00000000 --- a/docs/source/sections/example_routepath.html +++ /dev/null @@ -1,4 +0,0 @@ - \ No newline at end of file From edbd389dd65679b3346aec8b16e66a79182ab639 Mon Sep 17 00:00:00 2001 From: George Date: Fri, 16 Feb 2024 15:36:55 +0000 Subject: [PATCH 34/39] Minor text changes --- docs/source/sections/Installation.rst | 6 +++--- docs/source/sections/ipython_notebooks.rst | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/source/sections/Installation.rst b/docs/source/sections/Installation.rst index fd2d42ea..d261d6a2 100644 --- a/docs/source/sections/Installation.rst +++ b/docs/source/sections/Installation.rst @@ -2,7 +2,7 @@ Installation ************ -In this section we will outline the installation steps for installing the software package on a corresponding OS. +In this section we outline the necessary steps for installing the MeshiPhi software package. MeshiPhi requires a pre-existing installation of Python 3.8 or higher. Installing MeshiPhi @@ -24,8 +24,8 @@ Github: pip install . -Installing GDAL -############### +Installing GDAL (Optional) +########################## The MeshiPhi software has GDAL as an optional requirement. It is only used when exporting TIFF images, so if this is not useful to you, we would recommend steering clear. It is not trivial and is a common source of problems. diff --git a/docs/source/sections/ipython_notebooks.rst b/docs/source/sections/ipython_notebooks.rst index c1e8fcff..48410962 100644 --- a/docs/source/sections/ipython_notebooks.rst +++ b/docs/source/sections/ipython_notebooks.rst @@ -2,9 +2,9 @@ Examples ##################################### -Digital environement files (meshes) can be created using the MeshiPhi package, either through the +Digital environment files (meshes) can be created using the MeshiPhi package, either through the command line interface (CLI) or through the python terminal. This section will provide examples of how to create a digital -environement file using the python terminal. +environment file using the python terminal. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ From 1bc396f63433190a84eec5863014a8c9633d154d Mon Sep 17 00:00:00 2001 From: Samuel Hall <96304883+SamuelHall700@users.noreply.github.com> Date: Fri, 16 Feb 2024 16:00:34 +0000 Subject: [PATCH 35/39] removing references to route planning in overview section --- docs/html/.doctrees/environment.pickle | Bin 442466 -> 441970 bytes .../.doctrees/sections/Code_overview.doctree | Bin 10439 -> 8169 bytes .../_sources/sections/Code_overview.rst.txt | 5 ----- docs/html/index.html | 3 +-- docs/html/objects.inv | Bin 5357 -> 5343 bytes docs/html/searchindex.js | 2 +- docs/html/sections/Code_overview.html | 9 ++------- docs/source/sections/Code_overview.rst | 5 ----- 8 files changed, 4 insertions(+), 20 deletions(-) diff --git a/docs/html/.doctrees/environment.pickle b/docs/html/.doctrees/environment.pickle index f42abe489e319ab3013f3aede26120633da67f48..5bcd3b3fb4825332ed7c26c4ce94856247669a16 100644 GIT binary patch literal 441970 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 YFyEY% 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 diff --git a/docs/html/.doctrees/sections/Code_overview.doctree b/docs/html/.doctrees/sections/Code_overview.doctree index e444feb3d762474631169e7a6e9be0adb666b624..af014108328cf30d0da4170f1c85e28cdcdcf1db 100644 GIT binary patch delta 727 zcmZ{h&1(};6vcZd4C%zAnZ_oR%tt0Dm|9~=rJD*Vel4^Z5D^P%=v0&3PVF>JXBGtu z1}Yc{WN}Au>!OILU>VRqL05txE)>K?T_{Dwr7Pc?)KrviF7KUt-a9|;eRbjMlz3ab z|0%O6z5r@Q3iJ(*?+?3kD7B@!*)VGjvyL8l{?ABJpm$P{?AQY+Q6V-iMo_`LUmTbK zsE`w{f=wUeIy7iAtx!_ViFIbUNrM9_mE|#5qcKINr}D9wg&H0~eLBkeHQJV6LygXB z<08LbXMSVIWT!H!80tDp3~0_b5>p{qpxNY^eaj7%Q6vwkk9LG)E)J}*INt}r&$f0r61`wi1L;~6aNJ&wkEr&>q*JIC^_0BRg zYc~h9AQY4!6VZ;##{q-{2Tst+Qn*A&T%d;@5aJ3F2P8PbfddDSc(Y!o350_sUy|L~ z_vZcH|Gnp#UzfjmHuh@l`d;p4Y}Y!Oe3BOlTCEXLW2D}s@%1L1Y#d(IKUwF4A-_Nq zjf95Xgxu_8qzxUWdwbFk|&w~VSp zQC>tPE|4z?Dr^{QW|O>Bg1BWxi3?6OA|-JU_lUsCxUs-R9(S-nf|MC|Hs2OPs(hEAcwo;`2v=mbde2&O8B+{RD?ZGaBPD;N4%ggY#oXs zVFRp?gbZbABl3Z-N_J9$^g*bq0Syo@wF6S-89LA`7b zrXH7)6&&Dvjxxx$&Y{Y$$C1x{d8GtWC;i1?>9ug;tAXNYiSQL?qYpe{4 zfv%D}zIl*F4yd?`+Jy#7cvY;*puwU}I-sPnHYOO72>%f*QIS`f8}=)7q$Id4FSw<(lo0dZeMZ3!BJAlQ*StQE5{=wcc|LOH##!+{DF zpi!V7qG>v-|A;@Byc&U|z-C83GmeBYzu3J~novkr1Q==L4L~ zP5Pr@IKI`0!&)5+x4A`k^;gNceWWx5zTNsQS+T6!A(L6SWtftOm^2=n)jy1#PQ4D_ z4~m;=Wly|ljaNpjzP@$>D>Q5Puj!ps{`fw4Iwu$y7gU#4F^l4^N8dq>X7qneJ- z3_kW>qDTIp=v+iJyW5DvZPD|UJQ`tT;(=Hj##9@~=*8B}iCDjd^%s-RTQBKkCO^zz zH(MW8Dp$J%UrfbTk*R~{nl>Fz31nFmAAp5@|JN~qZcY$=4})H_>F`M nH#@cA5os>D6=Sze*S15GZJ*AW#n5k*UZDBV325HQu37&8i(vtO diff --git a/docs/html/_sources/sections/Code_overview.rst.txt b/docs/html/_sources/sections/Code_overview.rst.txt index 65ddcb9c..075ba939 100644 --- a/docs/html/_sources/sections/Code_overview.rst.txt +++ b/docs/html/_sources/sections/Code_overview.rst.txt @@ -2,11 +2,6 @@ Background ********** -Code Overview -############# - -We present an automated route-planning method for use by an ice-strengthened vessel operating in polar regions. We build on the method developed for underwater vehicle long-distance route planning reported in Fox et al (2021). We start with the same grid-based route construction approach to obtain routes that satisfy constraints on the performance of the ship in ice. We then apply a novel route-smoothing method to the resulting routes, shortening the grid-based routes and ensure that routes follow great circle arcs where possible. This two-stage process efficiently generates routes that follow standard navigation solutions in open water and optimise vessel performance in and around areas dominated by sea ice. While we have focussed on navigation in and around polar ice, our methods are also applicable to shipping in a broader context (e.g.: commercial shipping) where route-planning must be responsive to changing local and weather conditions. - Code Structure ############## diff --git a/docs/html/index.html b/docs/html/index.html index 0c3cad56..5f2e3f3a 100644 --- a/docs/html/index.html +++ b/docs/html/index.html @@ -113,8 +113,7 @@

    Welcome to the MeshiPhi Manual Pages4. Background
  • 5. Configuration Overview