diff --git a/nes/nc_projections/default_nes.py b/nes/nc_projections/default_nes.py index d716b35918de93cc494265f957b476f7ac7d591a..604acb10dae9eb5369acd5549753be7214d969db 100644 --- a/nes/nc_projections/default_nes.py +++ b/nes/nc_projections/default_nes.py @@ -13,7 +13,7 @@ from cfunits import Units from numpy.ma.core import MaskError import geopandas as gpd from shapely.geometry import Polygon -from copy import deepcopy +from copy import deepcopy, copy import datetime from ..interpolation import vertical_interpolation from ..interpolation import horizontal_interpolation @@ -144,6 +144,10 @@ class Nes(object): self.hours_end = avoid_last_hours self.first_level = first_level self.last_level = last_level + self.lat_min = None + self.lat_max = None + self.lon_min = None + self.lon_max = None self.balanced = balanced # Define parallel method @@ -216,7 +220,8 @@ class Nes(object): self.lev = self._get_coordinate_values(self._lev, 'Z') self.lat = self._get_coordinate_values(self._lat, 'Y') self.lon = self._get_coordinate_values(self._lon, 'X') - self.lat_bnds, self.lon_bnds = self._lat_bnds, self._lon_bnds + self.lat_bnds = self._get_coordinate_values(self._lat_bnds, 'Y', bounds=True) + self.lon_bnds = self._get_coordinate_values(self._lon_bnds, 'X', bounds=True) # Set axis limits for parallel writing self.write_axis_limits = self.get_write_axis_limits() @@ -611,6 +616,137 @@ class Nes(object): aux_nessy.variables[var_name]['data'] = aux_nessy.variables[var_name]['data'][[idx_time]] return aux_nessy + def sel(self, hours_start=None, time_min=None, hours_end=None, time_max=None, lev_min=None, lev_max=None, + lat_min=None, lat_max=None, lon_min=None, lon_max=None): + loaded_vars = False + for var_info in self.variables.values(): + if var_info['data'] is not None: + loaded_vars = True + # var_info['data'] = None + if loaded_vars: + raise ValueError("Some variables have been loaded. Use select function before load.") + + # First time filter + if hours_start is not None: + if time_min is not None: + raise ValueError("Choose to select by hours_start or time_min but not both") + self.hours_start = hours_start + elif time_min is not None: + if time_min <= self._time[0]: + self.hours_start = 0 + else: + self.hours_start = int((time_min - self._time[0]).total_seconds() // 3600) + + # Last time Filter + if hours_end is not None: + if time_max is not None: + raise ValueError("Choose to select by hours_end or time_max but not both") + self.hours_end = hours_end + elif time_max is not None: + if time_max >= self._time[-1]: + self.hours_end = 0 + else: + self.hours_end = int((self._time[-1] - time_max).total_seconds() // 3600) + + # Level filter + self.first_level = lev_min + self.last_level = lev_max + + # Coordinate filter + self.lat_min = lat_min + self.lat_max = lat_max + self.lon_min = lon_min + self.lon_max = lon_max + + # New Axis limits + self.read_axis_limits = self.get_read_axis_limits() + # Dimensions screening + self.time = self._time[self.read_axis_limits['t_min']:self.read_axis_limits['t_max']] + self.time_bnds = self._time_bnds + self.lev = self._get_coordinate_values(self._lev, 'Z') + self.lat = self._get_coordinate_values(self._lat, 'Y') + self.lon = self._get_coordinate_values(self._lon, 'X') + + self.lat_bnds = self._get_coordinate_values(self._lat_bnds, 'Y', bounds=True) + self.lon_bnds = self._get_coordinate_values(self._lon_bnds, 'X', bounds=True) + + # Removing complete coordinates + self.write_axis_limits = self.get_write_axis_limits() + + self.filter_coordinates_selection() + + return None + + def filter_coordinates_selection(self): + idx = self.get_idx_intervals() + + self._time = self._time[idx['idx_t_min']:idx['idx_t_max']] + + if len(self._lat['data'].shape) == 1: + # Regular projection + self._lat['data'] = self._lat['data'][idx['idx_y_min']:idx['idx_y_max']] + self._lon['data'] = self._lon['data'][idx['idx_x_min']:idx['idx_x_max']] + + if self._lat_bnds is not None: + self._lat_bnds = self._lat_bnds[idx['idx_y_min']:idx['idx_y_max'], :] + if self._lon_bnds is not None: + self._lon_bnds = self._lon_bnds[idx['idx_x_min']:idx['idx_x_max'], :] + else: + # Irregular projections + self._lat['data'] = self._lat['data'][idx['idx_y_min']:idx['idx_y_max'], idx['idx_x_min']:idx['idx_x_max']] + self._lon['data'] = self._lon['data'][idx['idx_y_min']:idx['idx_y_max'], idx['idx_x_min']:idx['idx_x_max']] + + if self._lat_bnds is not None: + self._lat_bnds = self._lat_bnds[idx['idx_y_min']:idx['idx_y_max'], idx['idx_x_min']:idx['idx_x_max'], :] + if self._lon_bnds is not None: + self._lon_bnds = self._lon_bnds[idx['idx_y_min']:idx['idx_y_max'], idx['idx_x_min']:idx['idx_x_max'], :] + + return None + + def get_idx_intervals(self): + idx = {'idx_t_min': self.get_time_id(self.hours_start, first=True), + 'idx_t_max': self.get_time_id(self.hours_end, first=False)} + + # Axis Y + if self.lat_min is None: + idx['idx_y_min'] = 0 + else: + idx['idx_y_min'] = self.get_coordinate_id(self._lat['data'], self.lat_min, axis=0) + if self.lat_max is None: + idx['idx_y_max'] = self._lat['data'].shape[0] + 1 + else: + idx['idx_y_max'] = self.get_coordinate_id(self._lat['data'], self.lat_max, axis=0) + 1 + + if idx['idx_y_min'] > idx['idx_y_max']: + idx_aux = copy(idx['idx_y_min']) + idx['idx_y_min'] = idx['idx_y_max'] + idx['idx_y_max'] = idx_aux + + # Axis X + + if self.lon_min is None: + idx['idx_x_min'] = 0 + else: + if len(self._lon['data'].shape) == 1: + axis = 0 + else: + axis = 1 + idx['idx_x_min'] = self.get_coordinate_id(self._lon['data'], self.lon_min, axis=axis) + if self.lon_max is None: + idx['idx_x_max'] = self._lon['data'].shape[-1] + 1 + else: + if len(self._lon['data'].shape) == 1: + axis = 0 + else: + axis = 1 + idx['idx_x_max'] = self.get_coordinate_id(self._lon['data'], self.lon_max, axis=axis) + 1 + + if idx['idx_x_min'] > idx['idx_x_max']: + idx_aux = copy(idx['idx_x_min']) + idx['idx_x_min'] = idx['idx_x_max'] + idx['idx_x_max'] = idx_aux + return idx + # ================================================================================================================== # Statistics # ================================================================================================================== @@ -792,36 +928,60 @@ class Nes(object): 'y_min': None, 'y_max': None, 'z_min': None, 'z_max': None, 't_min': None, 't_max': None} - + + idx = self.get_idx_intervals() + if self.parallel_method == 'Y': - y_len = self._lat['data'].shape[0] + y_len = idx['idx_y_max'] - idx['idx_y_min'] if y_len < self.size: - raise IndexError('More processors (size={0}) selected than Y elements (size={1})'.format(self.size, y_len)) - axis_limits['y_min'] = (y_len // self.size) * self.rank + raise IndexError('More processors (size={0}) selected than Y elements (size={1})'.format( + self.size, y_len)) + axis_limits['y_min'] = ((y_len // self.size) * self.rank) + idx['idx_y_min'] if self.rank + 1 < self.size: - axis_limits['y_max'] = (y_len // self.size) * (self.rank + 1) - # Spin up - axis_limits['t_min'] = self.get_time_id(self.hours_start, first=True) - axis_limits['t_max'] = self.get_time_id(self.hours_end, first=False) + axis_limits['y_max'] = ((y_len // self.size) * (self.rank + 1)) + idx['idx_y_max'] + else: + axis_limits['y_max'] = idx['idx_y_max'] + + # Non parallel filters + axis_limits['x_min'] = idx['idx_x_min'] + axis_limits['x_max'] = idx['idx_x_max'] + + axis_limits['t_min'] = idx['idx_t_min'] + axis_limits['t_max'] = idx['idx_t_max'] + elif self.parallel_method == 'X': - x_len = self._lon['data'].shape[-1] + x_len = idx['idx_x_max'] - idx['idx_x_min'] if x_len < self.size: - raise IndexError('More processors (size={0}) selected than X elements (size={1})'.format(self.size, x_len)) - axis_limits['x_min'] = (x_len // self.size) * self.rank + raise IndexError('More processors (size={0}) selected than X elements (size={1})'.format( + self.size, x_len)) + axis_limits['x_min'] = ((x_len // self.size) * self.rank) + idx['idx_x_min'] if self.rank + 1 < self.size: - axis_limits['x_max'] = (x_len // self.size) * (self.rank + 1) - # Spin up - axis_limits['t_min'] = self.get_time_id(self.hours_start, first=True) - axis_limits['t_max'] = self.get_time_id(self.hours_end, first=False) + axis_limits['x_max'] = ((x_len // self.size) * (self.rank + 1)) + idx['idx_x_max'] + else: + axis_limits['x_max'] = idx['idx_x_max'] + + # Non parallel filters + axis_limits['y_min'] = idx['idx_y_min'] + axis_limits['y_max'] = idx['idx_y_max'] + + axis_limits['t_min'] = idx['idx_t_min'] + axis_limits['t_max'] = idx['idx_t_max'] + elif self.parallel_method == 'T': - first_time_idx = self.get_time_id(self.hours_start, first=True) - last_time_idx = self.get_time_id(self.hours_end, first=False) - t_len = last_time_idx - first_time_idx + t_len = idx['idx_t_min'] - idx['idx_t_max'] if t_len < self.size: - raise IndexError('More processors (size={0}) selected than T elements (size={1})'.format(self.size, t_len)) - axis_limits['t_min'] = ((t_len // self.size) * self.rank) + first_time_idx + raise IndexError('More processors (size={0}) selected than T elements (size={1})'.format( + self.size, t_len)) + axis_limits['t_min'] = ((t_len // self.size) * self.rank) + idx['idx_t_min'] if self.rank + 1 < self.size: - axis_limits['t_max'] = ((t_len // self.size) * (self.rank + 1)) + first_time_idx + axis_limits['t_max'] = ((t_len // self.size) * (self.rank + 1)) + idx['idx_t_max'] + + # Non parallel filters + axis_limits['y_min'] = idx['idx_y_min'] + axis_limits['y_max'] = idx['idx_y_max'] + + axis_limits['x_min'] = idx['idx_x_min'] + axis_limits['x_max'] = idx['idx_x_max'] else: raise NotImplementedError("Parallel method '{meth}' is not implemented. Use one of these: {accept}".format( @@ -831,7 +991,7 @@ class Nes(object): axis_limits['z_min'] = self.first_level if self.last_level == -1 or self.last_level is None: self.last_level = None - elif self.last_level +1 == len(self._lev['data']): + elif self.last_level + 1 == len(self._lev['data']): self.last_level = None else: self.last_level += 1 @@ -849,33 +1009,33 @@ class Nes(object): Dictionary with the 4D limits of the rank data to read. t_min, t_max, z_min, z_max, y_min, y_max, x_min and x_max. """ + idx = self.get_idx_intervals() fid_dist = {} - to_add = None if self.parallel_method == 'Y': - len_to_split = self._lat['data'].shape[0] + len_to_split = idx['idx_y_max'] - idx['idx_y_min'] if len_to_split < self.size: raise IndexError('More processors (size={0}) selected than Y elements (size={1})'.format( self.size, len_to_split)) min_axis = 'y_min' max_axis = 'y_max' + to_add = idx['idx_y_min'] elif self.parallel_method == 'X': - len_to_split = self._lon['data'].shape[-1] + len_to_split = idx['idx_x_max'] - idx['idx_x_min'] if len_to_split < self.size: raise IndexError('More processors (size={0}) selected than X elements (size={1})'.format( self.size, len_to_split)) min_axis = 'x_min' max_axis = 'x_max' + to_add = idx['idx_x_min'] elif self.parallel_method == 'T': - first_time_idx = self.get_time_id(self.hours_start, first=True) - last_time_idx = self.get_time_id(self.hours_end, first=False) - len_to_split = last_time_idx - first_time_idx + len_to_split = idx['idx_t_max'] - idx['idx_t_min'] if len_to_split < self.size: raise IndexError('More processors (size={0}) selected than T elements (size={1})'.format( self.size, len_to_split)) min_axis = 't_min' max_axis = 't_max' - to_add = first_time_idx + to_add = idx['idx_t_min'] else: raise NotImplementedError("Parallel method '{meth}' is not implemented. Use one of these: {accept}".format( meth=self.parallel_method, accept=['X', 'Y', 'T'])) @@ -915,10 +1075,16 @@ class Nes(object): axis_limits = fid_dist[self.rank] + # Non parallel filters if self.parallel_method != 'T': - # Spin up - axis_limits['t_min'] = self.get_time_id(self.hours_start, first=True) - axis_limits['t_max'] = self.get_time_id(self.hours_end, first=False) + axis_limits['t_min'] = idx['idx_t_min'] + axis_limits['t_max'] = idx['idx_t_max'] + if self.parallel_method != 'X': + axis_limits['x_min'] = idx['idx_x_min'] + axis_limits['x_max'] = idx['idx_x_max'] + if self.parallel_method != 'Y': + axis_limits['y_min'] = idx['idx_y_min'] + axis_limits['y_max'] = idx['idx_y_max'] # Vertical levels selection: axis_limits['z_min'] = self.first_level @@ -959,6 +1125,27 @@ class Nes(object): return idx + def get_coordinate_id(self, array, value, axis=0): + """ + Get the index of the corresponding coordinate value. + + Parameters + ---------- + value : float + Coordinate value to search. + min : bool + Indicates if you want to apply the filter as minimum (True) or maximum (False) values + Default: True. + + Returns + ------- + int + Index of the coordinate array. + """ + idx = (np.abs(array - value)).argmin(axis=axis).min() + + return idx + def open(self): """ Open the NetCDF. @@ -1263,7 +1450,7 @@ class Nes(object): return nc_var - def _get_coordinate_values(self, coordinate_info, coordinate_axis): + def _get_coordinate_values(self, coordinate_info, coordinate_axis, bounds=False): """ Get the coordinate data of the current portion. @@ -1278,11 +1465,17 @@ class Nes(object): values : dict Dictionary with the portion of data corresponding to the rank. """ + if coordinate_info is None: + return None - values = deepcopy(coordinate_info) - if isinstance(coordinate_info, list): + if not isinstance(coordinate_info, dict): values = {'data': deepcopy(coordinate_info)} + else: + values = deepcopy(coordinate_info) + coordinate_len = len(values['data'].shape) + if bounds: + coordinate_len -= 1 if coordinate_axis == 'Y': if coordinate_len == 1: @@ -1713,7 +1906,7 @@ class Nes(object): # LATITUDES BOUNDS if self._lat_bnds is not None: lat_bnds_var = netcdf.createVariable('lat_bnds', np.float64, self._lat_dim + ('spatial_nv',), - zlib=self.zip_lvl, complevel=self.zip_lvl) + zlib=self.zip_lvl > 0, complevel=self.zip_lvl) if self.size > 1: lat_bnds_var.set_collective(True) lat_bnds_var[:] = self._lat_bnds[:] @@ -1733,7 +1926,7 @@ class Nes(object): # LONGITUDES BOUNDS if self._lon_bnds is not None: lon_bnds_var = netcdf.createVariable('lon_bnds', np.float64, self._lon_dim + ('spatial_nv',), - zlib=self.zip_lvl, complevel=self.zip_lvl) + zlib=self.zip_lvl > 0, complevel=self.zip_lvl) if self.size > 1: lon_bnds_var.set_collective(True) lon_bnds_var[:] = self._lon_bnds[:] @@ -1909,7 +2102,7 @@ class Nes(object): return None - def to_netcdf(self, path, compression_level=0, serial=False, info=False, + def to_netcdf(self, path, compression_level=0, serial=False, info=False, chunking=False): """ Write the netCDF output file. diff --git a/nes/nc_projections/lcc_nes.py b/nes/nc_projections/lcc_nes.py index e8048044774c87488130d87ade90335717c5663d..ef41fb3c5c2bc9c68c7f38f1ee0a24147ec784c7 100644 --- a/nes/nc_projections/lcc_nes.py +++ b/nes/nc_projections/lcc_nes.py @@ -124,6 +124,20 @@ class LCCNes(Nes): return new + def filter_coordinates_selection(self): + + idx = self.get_idx_intervals() + + self.y = self._get_coordinate_values(self._y, 'Y') + self.x = self._get_coordinate_values(self._x, 'X') + + self._y['data'] = self._y['data'][idx['idx_y_min']:idx['idx_y_max']] + self._x['data'] = self._x['data'][idx['idx_x_min']:idx['idx_x_max']] + + super(LCCNes, self).filter_coordinates_selection() + + return None + def get_projection_data(self, create_nes, **kwargs): """ Read the projection data. diff --git a/nes/nc_projections/mercator_nes.py b/nes/nc_projections/mercator_nes.py index 4ca7d4e3cb91e18d0acc67a7ab784700377c06bc..3e10ef6d1f2e456eab677b4ed07173849020f07d 100644 --- a/nes/nc_projections/mercator_nes.py +++ b/nes/nc_projections/mercator_nes.py @@ -124,6 +124,20 @@ class MercatorNes(Nes): return new + def filter_coordinates_selection(self): + + idx = self.get_idx_intervals() + + self.y = self._get_coordinate_values(self._y, 'Y') + self.x = self._get_coordinate_values(self._x, 'X') + + self._y['data'] = self._y['data'][idx['idx_y_min']:idx['idx_y_max']] + self._x['data'] = self._x['data'][idx['idx_x_min']:idx['idx_x_max']] + + super(MercatorNes, self).filter_coordinates_selection() + + return None + def get_projection_data(self, create_nes, **kwargs): """ Read the projection data. diff --git a/nes/nc_projections/rotated_nes.py b/nes/nc_projections/rotated_nes.py index 54f9e44d2a4ef4068e0303878a4bf8a27a07d0f9..df82944b1841bb971d9f64d4c84d07d7d7bbcf0f 100644 --- a/nes/nc_projections/rotated_nes.py +++ b/nes/nc_projections/rotated_nes.py @@ -125,6 +125,20 @@ class RotatedNes(Nes): avoid_last_hours=avoid_last_hours, first_level=first_level, last_level=last_level) return new + def filter_coordinates_selection(self): + + idx = self.get_idx_intervals() + + self.rlat = self._get_coordinate_values(self._rlat, 'Y') + self.rlon = self._get_coordinate_values(self._rlon, 'X') + + self._rlat['data'] = self._rlat['data'][idx['idx_y_min']:idx['idx_y_max']] + self._rlon['data'] = self._rlon['data'][idx['idx_x_min']:idx['idx_x_max']] + + super(RotatedNes, self).filter_coordinates_selection() + + return None + def get_projection_data(self, create_nes, **kwargs): """ Read the projection data. diff --git a/tutorials/5.Others/5.3.Selecting.ipynb b/tutorials/5.Others/5.3.Selecting.ipynb new file mode 100644 index 0000000000000000000000000000000000000000..c37d18225ae5c47c85f06a4dd0061eebc957b721 --- /dev/null +++ b/tutorials/5.Others/5.3.Selecting.ipynb @@ -0,0 +1,271 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Test slecting" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "from nes import *\n", + "file_path = \"/gpfs/scratch/bsc32/bsc32538/original_files/CAMS_MONARCH_d01_2022070412.nc\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Time" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2022-07-04 12:00:00 109 2022-07-09 00:00:00\n" + ] + }, + { + "data": { + "text/plain": [ + "'\\nCPU times: user 1.17 s, sys: 6.79 s, total: 7.96 s\\nWall time: 31.4 s\\n'" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "nessy = open_netcdf(file_path)\n", + "nessy.keep_vars('O3')\n", + "\n", + "print(nessy.time[0], len(nessy.time), nessy.time[-1])\n", + "# %time nessy.load()\n", + "\"\"\"\n", + "CPU times: user 1.17 s, sys: 6.79 s, total: 7.96 s\n", + "Wall time: 31.4 s\n", + "\"\"\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Hours filter" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2022-07-05 00:00:00 24 2022-07-05 23:00:00\n" + ] + }, + { + "data": { + "text/plain": [ + "'\\nCPU times: user 295 ms, sys: 1.47 s, total: 1.76 s\\nWall time: 6.77 s\\n'" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "nessy = open_netcdf(file_path)\n", + "nessy.keep_vars('O3')\n", + "\n", + "nessy.sel(hours_start=12, hours_end=73)\n", + "\n", + "print(nessy.time[0], len(nessy.time), nessy.time[-1])\n", + "# %time nessy.load()\n", + "\"\"\"\n", + "CPU times: user 295 ms, sys: 1.47 s, total: 1.76 s\n", + "Wall time: 6.77 s\n", + "\"\"\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Time filter" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2022-07-05 00:00:00 24 2022-07-05 23:00:00\n" + ] + }, + { + "data": { + "text/plain": [ + "'\\nCPU times: user 274 ms, sys: 1.44 s, total: 1.71 s\\nWall time: 7.53 s\\n'" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from datetime import datetime\n", + "\n", + "nessy = open_netcdf(file_path)\n", + "nessy.keep_vars('O3')\n", + "\n", + "nessy.sel(time_min=datetime(year=2022, month=7, day=5, hour=0), \n", + " time_max=datetime(year=2022, month=7, day=5, hour=23))\n", + "\n", + "print(nessy.time[0], len(nessy.time), nessy.time[-1])\n", + "# %time nessy.load()\n", + "\"\"\"\n", + "CPU times: user 274 ms, sys: 1.44 s, total: 1.71 s\n", + "Wall time: 7.53 s\n", + "\"\"\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Level" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1\n" + ] + }, + { + "data": { + "text/plain": [ + "'\\nCPU times: user 77.3 ms, sys: 248 ms, total: 325 ms\\nWall time: 17.1 s\\n'" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "nessy = open_netcdf(file_path)\n", + "nessy.keep_vars('O3')\n", + "\n", + "nessy.sel(lev_min=23)\n", + "\n", + "print(len(nessy.lev['data']))\n", + "# %time nessy.load()\n", + "\"\"\"\n", + "CPU times: user 77.3 ms, sys: 248 ms, total: 325 ms\n", + "Wall time: 17.1 s\n", + "\"\"\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Coordinate" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU times: user 16.4 ms, sys: 79.8 ms, total: 96.2 ms\n", + "Wall time: 18.6 s\n" + ] + }, + { + "data": { + "text/plain": [ + "'\\nCPU times: user 13.9 ms, sys: 74.9 ms, total: 88.8 ms\\nWall time: 16.3 s\\n'" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "nessy = open_netcdf(file_path)\n", + "nessy.keep_vars('O3')\n", + "\n", + "nessy.sel(lat_min=30, lat_max=31, lon_min=-1, lon_max=1)\n", + "%time nessy.load()\n", + "\"\"\"\n", + "CPU times: user 13.9 ms, sys: 74.9 ms, total: 88.8 ms\n", + "Wall time: 16.3 s\n", + "\"\"\"" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "nessy.to_netcdf(\"test_sel.nc\")" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.4" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +}