def __init__(self, input_config: InputConfig = None, input_configs: Sequence[InputConfig] = None, cube_config: CubeConfig = None, code_config: CodeConfig = None, output_config: OutputConfig = None, callback_config: Optional[CallbackConfig] = None): assert_true(input_config or input_configs, 'one of input_config and input_configs must be given') assert_false(input_config and input_configs, 'input_config and input_configs cannot be given both') if input_config is not None: assert_instance(input_config, InputConfig, 'input_config') input_configs = [input_config] elif input_configs is not None: assert_instance(input_configs, (list, tuple), 'input_configs') for i in range(len(input_configs)): assert_instance(input_configs[i], InputConfig, f'input_configs[{i}]') if cube_config is not None: assert_instance(cube_config, CubeConfig, 'cube_config') if code_config is not None: assert_instance(code_config, CodeConfig, 'code_config') assert_instance(output_config, OutputConfig, 'output_config') if callback_config is not None: assert_instance(callback_config, CallbackConfig, 'callback_config') self.input_configs = input_configs self.cube_config = cube_config self.code_config = code_config self.output_config = output_config self.callback_config = callback_config
def set_callable(self, func_or_class: Callable): """ Set the callable that is represented by this configuration. :param func_or_class: A callable """ assert_true(callable(func_or_class), f'func_or_class must be callable') self._callable = func_or_class
def _assert_valid_xy_coords(xy_coords: Any): assert_instance(xy_coords, xr.DataArray, name='xy_coords') assert_true( xy_coords.ndim == 3 and xy_coords.shape[0] == 2 and xy_coords.shape[1] >= 2 and xy_coords.shape[2] >= 2, 'xy_coords must have dimensions' ' (2, height, width) with height >= 2 and width >= 2')
def _inject_attrs(self, attrs: Dict[str, Any]): assert_instance(attrs, dict, name='attrs') schema = self.get_schema() assert_true(isinstance(schema, JsonObjectSchema), message='schema must be a JSON object schema') all_attrs = {k: None for k in (schema.properties or {}).keys()} all_attrs.update(attrs) JsonObjectSchema.inject_attrs(self, all_attrs)
def worked(self, work: float): assert_true(self._state_stack, 'worked() method call is missing a current context') assert_true(work > 0, 'work must be greater than zero') for s in reversed(self._state_stack): s.inc_work(work) work = s.to_super_work(work) self.emit_update()
def __init__(self, input_configs: Sequence[InputConfig], store_pool: DataStorePool = None): assert_true(len(input_configs) > 0, 'At least one input must be given') if store_pool is not None: assert_instance(store_pool, DataStorePool, 'store_pool') self._input_configs = input_configs self._store_pool = store_pool
def __init__(self, callback_config: CallbackConfig, minimum: float = 0, dt: float = 1, timeout: float = False): super().__init__(minimum=minimum, dt=dt, timeout=timeout) assert_true(callback_config.api_uri and callback_config.access_token, "Both, api_uri and access_token must be given.") self.callback_config = callback_config
def tile_grid(self) -> TileGrid: # we allow up to 1% dev assert_true(math.isclose(self.x_res, self.y_res, rel_tol=0.01), message='spatial resolutions must be' ' same in both directions') return ImageTileGrid(image_size=self.size, tile_size=self.tile_size or (512, 512), crs=self.crs, xy_res=self.x_res, xy_min=(self.x_min, self.y_min), is_j_axis_up=self.is_j_axis_up)
def __init__(self, data_id: str, *, data_type: DataTypeLike = GEO_DATA_FRAME_TYPE, feature_schema: JsonObjectSchema = None, **kwargs): super().__init__(data_id=data_id, data_type=data_type, **kwargs) assert_true( GEO_DATA_FRAME_TYPE.is_super_type_of(data_type), f'illegal data_type,' f' must be compatible with {GEO_DATA_FRAME_TYPE!r}') self.feature_schema = feature_schema
def __init__(self, store_id: str = None, opener_id: str = None, data_id: str = None, store_params: Mapping[str, Any] = None, open_params: Mapping[str, Any] = None): assert_true(store_id or opener_id, 'One of store_id and opener_id must be given') assert_given(data_id, 'data_id') self.store_id = store_id self.opener_id = opener_id self.data_id = data_id self.store_params = store_params self.open_params = open_params
def __init__(self, data_id: str, num_levels: int, *, data_type: DataTypeLike = MULTI_LEVEL_DATASET_TYPE, **kwargs): assert_given(data_id, 'data_id') assert_given(num_levels, 'num_levels') super().__init__(data_id=data_id, data_type=data_type, **kwargs) assert_true( MULTI_LEVEL_DATASET_TYPE.is_super_type_of(data_type), f'illegal data_type,' f' must be compatible with {MULTI_LEVEL_DATASET_TYPE!r}') self.num_levels = num_levels
def __init__(self, store_id: str = None, writer_id: str = None, data_id: str = None, store_params: Mapping[str, Any] = None, write_params: Mapping[str, Any] = None, replace: bool = None): assert_true(store_id or writer_id, 'One of store_id and writer_id must be given') self.store_id = store_id self.writer_id = writer_id self.data_id = data_id self.store_params = store_params self.write_params = write_params self.replace = replace
def __init__(self, label: str, total_work: float, interval: float = 0.1, initial_interval: float = 0): super().__init__() assert_given(label, 'label') assert_true(total_work > 0, 'total_work must be greater than zero') self._label = label self._total_work = total_work self._state: Optional[ProgressState] = None self._initial_interval = initial_interval self._interval = interval self._last_worked = 0 self._running = False
def drop_props(self, name: Union[str, Iterable[str]]): """ Drop one or more named properties from this configuration. :param name: the name of the property to be dropped. :param names: more names of properties to be dropped. :return: a new cube configuration. """ if not name: return self name_set = {name} if isinstance(name, str) else set(name) for k in name_set: assert_true(hasattr(self, k), message=f'{k} is not a property of {CubeConfig!r}') return self.from_dict( {k: v for k, v in self.to_dict().items() if k not in name_set})
def new_regular_grid_mapping( size: Union[int, Tuple[int, int]], xy_min: Tuple[float, float], xy_res: Union[float, Tuple[float, float]], crs: Union[str, pyproj.crs.CRS], *, tile_size: Union[int, Tuple[int, int]] = None, is_j_axis_up: bool = False ) -> GridMapping: width, height = _normalize_int_pair(size, name='size') assert_true(width > 1 and height > 1, 'invalid size') x_min, y_min = _normalize_number_pair(xy_min, name='xy_min') x_res, y_res = _normalize_number_pair(xy_res, name='xy_res') assert_true(x_res > 0 and y_res > 0, 'invalid xy_res') crs = _normalize_crs(crs) x_min = _to_int_or_float(x_min) y_min = _to_int_or_float(y_min) x_max = _to_int_or_float(x_min + x_res * width) y_max = _to_int_or_float(y_min + y_res * height) if crs.is_geographic: # TODO: don't do that. # Instead set NaN in coord vars returned by to_coords() if y_min < -90: raise ValueError('invalid y_min') if y_max > 90: raise ValueError('invalid size, y_min combination') return RegularGridMapping( crs=crs, size=(width, height), tile_size=tile_size or (width, height), xy_bbox=(x_min, y_min, x_max, y_max), xy_res=(x_res, y_res), xy_var_names=_default_xy_var_names(crs), xy_dim_names=_default_xy_dim_names(crs), is_regular=True, is_lon_360=x_max > 180, is_j_axis_up=is_j_axis_up )
def __init__(self, minimum: float = 0, dt: float = 1, timeout: float = None): """ :type dt: float :type minimum: float """ super().__init__() assert_true(dt >= 0, "The timer's time step must be >=0") assert_true(minimum >= 0, "The timer's minimum must be >=0") self._running = False self._start_time = None self._minimum = minimum self._dt = dt self._width = 100 self._current_sender = None self._state_stack: [ProgressState] = [] self._timeout = timeout
def __init__(self, source_images: Sequence[TiledImage], image_id: str = None, encode: bool = False, format: str = None, tile_cache: Cache = None, trace_perf: bool = False): assert_instance(source_images, (list, tuple), name='source_images') assert_true(len(source_images) == 3, message='source_images must have length 3') proto_source_image = source_images[0] super().__init__(size=proto_source_image.size, tile_size=proto_source_image.tile_size, num_tiles=proto_source_image.num_tiles, image_id=image_id, format=format, mode='RGBA', tile_cache=tile_cache, trace_perf=trace_perf) self._source_images = tuple(source_images) self._encode = encode
def __init__(self, _callable: Callable = None, callable_ref: str = None, callable_params: Dict[str, Any] = None, inline_code: str = None, file_set: FileSet = None, install_required: bool = None): if callable_ref is not None: assert_instance(callable_ref, str, 'callable_ref') msg = ('callable_ref must have form ' '"module:function" or "module:class"') try: module_name, callable_name = \ _normalize_callable_ref(callable_ref) except ValueError: raise ValueError(msg) assert_true(module_name, msg) assert_true(callable_name, msg) if _callable is not None: assert_true(callable(_callable), '_callable must be a function or class') if callable_params is not None: assert_instance(callable_params, dict, 'callable_params') if inline_code is not None: assert_instance(inline_code, str, 'inline_code') if file_set is not None: assert_instance(file_set, FileSet, 'file_set') assert_true( sum((1 if v is not None else 0) for v in (_callable, inline_code, file_set)) == 1, '_callable, inline_code, file_set ' 'are mutually exclusive and one must be given') assert_true(not install_required or file_set is not None, 'install_required can only be used if file_set is given') self._callable = _callable self.callable_ref = callable_ref self.callable_params = callable_params self.inline_code = inline_code self.file_set = file_set self.install_required = install_required
def __init__(self, data_id: str, *, data_type: DataTypeLike = DATASET_TYPE, crs: str = None, bbox: Tuple[float, float, float, float] = None, time_range: Tuple[Optional[str], Optional[str]] = None, time_period: str = None, spatial_res: float = None, dims: Mapping[str, int] = None, coords: Mapping[str, 'VariableDescriptor'] = None, data_vars: Mapping[str, 'VariableDescriptor'] = None, attrs: Mapping[Hashable, any] = None, open_params_schema: JsonObjectSchema = None, **additional_properties): super().__init__(data_id=data_id, data_type=data_type, crs=crs, bbox=bbox, time_range=time_range, time_period=time_period, open_params_schema=open_params_schema) assert_true( DATASET_TYPE.is_super_type_of(data_type) or MULTI_LEVEL_DATASET_TYPE.is_super_type_of(data_type), f'illegal data_type,' f' must be compatible with {DATASET_TYPE!r}' f' or {MULTI_LEVEL_DATASET_TYPE!r}') if additional_properties: warnings.warn(f'Additional properties received;' f' will be ignored: {additional_properties}') self.dims = dict(dims) if dims else None self.spatial_res = spatial_res self.coords = coords if coords else None self.data_vars = data_vars if data_vars else None self.attrs = _attrs_to_json(attrs) if attrs else None
def write_data(self, data: Any, data_id: str = None, writer_id: str = None, replace: bool = False, **write_params) -> str: if self.read_only: raise DataStoreError('Data store is read-only.') if not writer_id: writer_id = self._guess_writer_id(data, data_id=data_id) writer = self._find_writer(writer_id=writer_id) write_params_schema = self._get_write_data_params_schema(writer) assert_valid_params(write_params, name='write_params', schema=write_params_schema) data_id = self._ensure_valid_data_id(writer_id, data_id=data_id) fs_path = self._convert_data_id_into_fs_path(data_id) self.fs.makedirs(self.root, exist_ok=True) written_fs_path = writer.write_data(data, fs_path, replace=replace, fs=self.fs, root=self.root, **write_params) # Verify, accessors fulfill their write_data() contract assert_true(fs_path == written_fs_path, message='FsDataAccessor implementations must ' 'return the data_id passed in.') # Return original data_id (which is a relative path). # Note: it would be cleaner to return written_fs_path # here, but it is an absolute path. # --> Possible solution: FsDataAccessor implementations # should be responsible for resolving their data_id into a # filesystem path by providing them both with fs and root # arguments. return data_id
def __init__(self, image_size: Tuple[int, int], tile_size: Tuple[int, int], crs: Union[str, pyproj.CRS], xy_res: float, xy_min: Tuple[float, float], is_j_axis_up: bool): image_width, image_height = image_size assert_true(image_width >= 2 and image_height >= 2, message='image_width and image_height must be >= 2') self._image_width = int(image_width) self._image_height = int(image_height) tile_width, tile_height = tile_size assert_true(tile_width >= 2 and tile_height >= 2, message='tile_width and tile_height must be >= 2') tile_width = min(image_width, tile_width) tile_height = min(image_height, tile_height) assert_true(xy_res > 0, message='xy_res must be > 0') # Find number of detail levels and number of tiles # at lowest detail level (level zero). # It is found once the number of tiles # in either direction becomes 1 after continuously # subdividing the image sizes by 2. num_levels = 1 image_level_width = image_width image_level_height = image_height while True: num_level_0_tiles_x = (image_level_width + tile_width - 1) \ // tile_width num_level_0_tiles_y = (image_level_height + tile_height - 1) \ // tile_height if num_level_0_tiles_x == 1 or num_level_0_tiles_y == 1: break image_level_width = (image_level_width + 1) // 2 image_level_height = (image_level_height + 1) // 2 num_levels += 1 x_min, y_min = xy_min extent = (x_min, y_min, x_min + image_width * xy_res, y_min + image_height * xy_res) factor = 1 << (num_levels - 1) max_resolution = xy_res * factor super().__init__(tile_size=(tile_width, tile_height), num_level_0_tiles=(num_level_0_tiles_x, num_level_0_tiles_y), crs=crs, max_resolution=max_resolution, extent=extent, is_j_axis_up=is_j_axis_up, max_level=num_levels - 1)
def inc_work(self, work: float): assert_true(work > 0, 'work must be greater than zero') self._completed_work += work
def new_grid_mapping_from_coords( x_coords: xr.DataArray, y_coords: xr.DataArray, crs: Union[str, pyproj.crs.CRS], *, tile_size: Union[int, Tuple[int, int]] = None, tolerance: float = DEFAULT_TOLERANCE, ) -> GridMapping: crs = _normalize_crs(crs) assert_instance(x_coords, xr.DataArray, name='x_coords') assert_instance(y_coords, xr.DataArray, name='y_coords') assert_true(x_coords.ndim in (1, 2), 'x_coords and y_coords must be either 1D or 2D arrays') assert_instance(tolerance, float, name='tolerance') assert_true(tolerance > 0.0, 'tolerance must be greater zero') if x_coords.name and y_coords.name: xy_var_names = str(x_coords.name), str(y_coords.name) else: xy_var_names = _default_xy_var_names(crs) tile_size = _normalize_int_pair(tile_size, default=None) is_lon_360 = None # None means "not yet known" if crs.is_geographic: is_lon_360 = bool(np.any(x_coords > 180)) x_res = 0 y_res = 0 if x_coords.ndim == 1: # We have 1D x,y coordinates cls = Coords1DGridMapping assert_true(x_coords.size >= 2 and y_coords.size >= 2, 'sizes of x_coords and y_coords 1D arrays must be >= 2') size = x_coords.size, y_coords.size x_dim, y_dim = x_coords.dims[0], y_coords.dims[0] x_diff = _abs_no_zero(x_coords.diff(dim=x_dim).values) y_diff = _abs_no_zero(y_coords.diff(dim=y_dim).values) if not is_lon_360 and crs.is_geographic: is_anti_meridian_crossed = np.any(np.nanmax(x_diff) > 180) if is_anti_meridian_crossed: x_coords = to_lon_360(x_coords) x_diff = _abs_no_zero(x_coords.diff(dim=x_dim)) is_lon_360 = True x_res, y_res = x_diff[0], y_diff[0] x_diff_equal = np.allclose(x_diff, x_res, atol=tolerance) y_diff_equal = np.allclose(y_diff, y_res, atol=tolerance) is_regular = x_diff_equal and y_diff_equal if is_regular: x_res = round_to_fraction(x_res, 5, 0.25) y_res = round_to_fraction(y_res, 5, 0.25) else: x_res = round_to_fraction(float(np.nanmedian(x_diff)), 2, 0.5) y_res = round_to_fraction(float(np.nanmedian(y_diff)), 2, 0.5) if tile_size is None \ and x_coords.chunks is not None \ and y_coords.chunks is not None: tile_size = (max(0, *x_coords.chunks[0]), max(0, *y_coords.chunks[0])) # Guess j axis direction is_j_axis_up = bool(y_coords[0] < y_coords[-1]) else: # We have 2D x,y coordinates cls = Coords2DGridMapping assert_true( x_coords.shape == y_coords.shape, 'shapes of x_coords and y_coords' ' 2D arrays must be equal') assert_true( x_coords.dims == y_coords.dims, 'dimensions of x_coords and y_coords' ' 2D arrays must be equal') y_dim, x_dim = x_coords.dims height, width = x_coords.shape size = width, height x = da.asarray(x_coords) y = da.asarray(y_coords) x_x_diff = _abs_no_nan(da.diff(x, axis=1)) x_y_diff = _abs_no_nan(da.diff(x, axis=0)) y_x_diff = _abs_no_nan(da.diff(y, axis=1)) y_y_diff = _abs_no_nan(da.diff(y, axis=0)) if not is_lon_360 and crs.is_geographic: is_anti_meridian_crossed = da.any(da.max(x_x_diff) > 180) \ or da.any(da.max(x_y_diff) > 180) if is_anti_meridian_crossed: x_coords = to_lon_360(x_coords) x = da.asarray(x_coords) x_x_diff = _abs_no_nan(da.diff(x, axis=1)) x_y_diff = _abs_no_nan(da.diff(x, axis=0)) is_lon_360 = True is_regular = False if da.all(x_y_diff == 0) and da.all(y_x_diff == 0): x_res = x_x_diff[0, 0] y_res = y_y_diff[0, 0] is_regular = \ da.allclose(x_x_diff[0, :], x_res, atol=tolerance) \ and da.allclose(x_x_diff[-1, :], x_res, atol=tolerance) \ and da.allclose(y_y_diff[:, 0], y_res, atol=tolerance) \ and da.allclose(y_y_diff[:, -1], y_res, atol=tolerance) if not is_regular: # Let diff arrays have same shape as original by # doubling last rows and columns. x_x_diff_c = da.concatenate([x_x_diff, x_x_diff[:, -1:]], axis=1) y_x_diff_c = da.concatenate([y_x_diff, y_x_diff[:, -1:]], axis=1) x_y_diff_c = da.concatenate([x_y_diff, x_y_diff[-1:, :]], axis=0) y_y_diff_c = da.concatenate([y_y_diff, y_y_diff[-1:, :]], axis=0) # Find resolution via area x_abs_diff = da.sqrt(da.square(x_x_diff_c) + da.square(x_y_diff_c)) y_abs_diff = da.sqrt(da.square(y_x_diff_c) + da.square(y_y_diff_c)) if crs.is_geographic: # Convert degrees into meters x_abs_diff_r = da.radians(x_abs_diff) y_abs_diff_r = da.radians(y_abs_diff) x_abs_diff = _ER * da.cos(x_abs_diff_r) * y_abs_diff_r y_abs_diff = _ER * y_abs_diff_r xy_areas = (x_abs_diff * y_abs_diff).flatten() xy_areas = da.where(xy_areas > 0, xy_areas, np.nan) # Get indices of min and max area xy_area_index_min = da.nanargmin(xy_areas) xy_area_index_max = da.nanargmax(xy_areas) # Convert area to edge length xy_res_min = math.sqrt(xy_areas[xy_area_index_min]) xy_res_max = math.sqrt(xy_areas[xy_area_index_max]) # Empirically weight min more than max xy_res = 0.7 * xy_res_min + 0.3 * xy_res_max if crs.is_geographic: # Convert meters back into degrees # print(f'xy_res in meters: {xy_res}') xy_res = math.degrees(xy_res / _ER) # print(f'xy_res in degrees: {xy_res}') # Because this is an estimation, we can round to a nice number xy_res = round_to_fraction(xy_res, digits=1, resolution=0.5) x_res, y_res = float(xy_res), float(xy_res) if tile_size is None and x_coords.chunks is not None: j_chunks, i_chunks = x_coords.chunks tile_size = max(0, *i_chunks), max(0, *j_chunks) if tile_size is not None: tile_width, tile_height = tile_size x_coords = x_coords.chunk((tile_height, tile_width)) y_coords = y_coords.chunk((tile_height, tile_width)) # Guess j axis direction is_j_axis_up = np.all(y_coords[0, :] < y_coords[-1, :]) or None assert_true(x_res > 0 and y_res > 0, 'internal error: x_res and y_res could not be determined', exception_type=RuntimeError) x_res, y_res = _to_int_or_float(x_res), _to_int_or_float(y_res) x_res_05, y_res_05 = x_res / 2, y_res / 2 x_min = _to_int_or_float(x_coords.min() - x_res_05) y_min = _to_int_or_float(y_coords.min() - y_res_05) x_max = _to_int_or_float(x_coords.max() + x_res_05) y_max = _to_int_or_float(y_coords.max() + y_res_05) return cls(x_coords=x_coords, y_coords=y_coords, crs=crs, size=size, tile_size=tile_size, xy_bbox=(x_min, y_min, x_max, y_max), xy_res=(x_res, y_res), xy_var_names=xy_var_names, xy_dim_names=(str(x_dim), str(y_dim)), is_regular=is_regular, is_lon_360=is_lon_360, is_j_axis_up=is_j_axis_up)
def will_work(self, work: float): assert_true(self._state_stack, 'will_work() method call is missing a current context') # noinspection PyProtectedMember self._state_stack[-1].super_work_ahead = work
def __init__(self, label: str, total_work: float): assert_given(label, 'label') assert_true(total_work > 0, 'total_work must be greater than zero') self._label = label self._total_work = total_work self._state: Optional[ProgressState] = None
def _compute_effective_cube_config(self) \ -> Tuple[CubeConfig, pyproj.crs.CRS, Sequence[pd.Timestamp]]: """ Compute the effective cube configuration. This method reflects the behaviour of the LocalCubeGenerator that would normalize, tailor, and optionally resample a dataset based on the dataset descriptor and the cube configuration parameters, in the case that a store is not able to do so. :return: effective cube configuration. """ request = self._request cube_config = request.cube_config \ if request.cube_config is not None else CubeConfig() crs = cube_config.crs if crs is None: crs = self.first_input_dataset_descriptor.crs if crs is None: crs = 'WGS84' try: resolved_crs = pyproj.crs.CRS.from_string(crs) except (ValueError, pyproj.exceptions.CRSError) as e: raise ValueError(f'crs is invalid: {e}') from e bbox = cube_config.bbox if bbox is None: bbox = self.first_input_dataset_descriptor.bbox try: x1, y1, x2, y2 = bbox except (TypeError, ValueError): raise ValueError('bbox must be a tuple (x1, y1, x2, y2)') assert_instance(x1, numbers.Number, 'x1 of bbox') assert_instance(y1, numbers.Number, 'y1 of bbox') assert_instance(x2, numbers.Number, 'x2 of bbox') assert_instance(y2, numbers.Number, 'y2 of bbox') if resolved_crs.is_geographic and x2 < x1: x2 += 360 bbox = x1, y1, x2, y2 spatial_res = cube_config.spatial_res if spatial_res is None: spatial_res = self.first_input_dataset_descriptor.spatial_res assert_instance(spatial_res, numbers.Number, 'spatial_res') assert_true(spatial_res > 0, 'spatial_res must be positive') tile_size = cube_config.tile_size if tile_size is not None: try: tile_width, tile_height = tile_size except (TypeError, ValueError): raise ValueError('tile_size must be a' ' tuple (tile_width, tile_height)') tile_size = tile_width, tile_height time_range = cube_config.time_range if time_range is None: time_range = None, None start_ts, end_ts = _parse_time_range(time_range) if start_ts is None or end_ts is None: default_time_range = \ self.first_input_dataset_descriptor.time_range if default_time_range is None: default_time_range = None, None default_start_ts, default_end_ts = \ _parse_time_range(default_time_range) if start_ts is None: start_ts = default_start_ts if start_ts is None: start_ts = pd.Timestamp(datetime.date.today()) if end_ts is None: end_ts = default_end_ts if end_ts is None: end_ts = pd.Timestamp(datetime.date.today()) \ + pd.Timedelta('1D') time_range = (start_ts.strftime("%Y-%m-%d"), end_ts.strftime("%Y-%m-%d")) time_period = cube_config.time_period if time_period is None: time_period = self.first_input_dataset_descriptor.time_period if time_period is None: time_period = '1D' assert_instance(time_period, str, 'time_period') try: resolved_time_range = pd.date_range(start=start_ts, end=end_ts, freq=time_period) except ValueError as e: raise ValueError(f'invalid time_range or time_period: {e}') from e variable_names = cube_config.variable_names if variable_names is None: variable_names = list( self.first_input_dataset_descriptor.data_vars.keys()) return CubeConfig( variable_names=variable_names, crs=crs, bbox=bbox, spatial_res=spatial_res, tile_size=tile_size, time_range=time_range, time_period=time_period), resolved_crs, resolved_time_range
def _assert_used_correctly(self): assert_true(self._state is not None, 'observe_progress() must be used with "with" statement')
def test_assert_true(self): assert_true(True, 'Should be true') with self.assertRaises(ValueError) as e: assert_true(False, 'Should be true') self.assertEqual(('Should be true', ), e.exception.args)
def __init__(self, api_uri: str = None, access_token: str = None): assert_true(api_uri and access_token, 'Both, api_uri and access_token must be given') self.api_uri = api_uri self.access_token = access_token
def __init__( self, variable_names: Sequence[str] = None, crs: str = None, bbox: Tuple[float, float, float, float] = None, spatial_res: Union[float, Tuple[float]] = None, tile_size: Union[int, Tuple[int, int]] = None, time_range: Tuple[str, Optional[str]] = None, time_period: str = None, chunks: Mapping[str, Optional[int]] = None, metadata: Mapping[str, Any] = None, variable_metadata: Mapping[str, Mapping[str, Any]] = None, ): self.variable_names = None if variable_names is not None: assert_true(len(variable_names) > 0, 'variable_names is invalid') self.variable_names = tuple(map(str, variable_names)) self.crs = None if crs is not None: assert_instance(crs, str, 'crs') try: pyproj.crs.CRS.from_string(crs) except pyproj.exceptions.CRSError: raise ValueError('crs is invalid') self.crs = crs self.bbox = None if bbox is not None: assert_true(len(bbox) == 4, 'bbox is invalid') self.bbox = tuple(map(float, bbox)) self.spatial_res = None if spatial_res is not None: assert_instance(spatial_res, numbers.Number, 'spatial_res') self.spatial_res = float(spatial_res) self.tile_size = None if tile_size is not None: if isinstance(tile_size, int): tile_width, tile_height = tile_size, tile_size else: try: tile_width, tile_height = tile_size except (ValueError, TypeError): raise ValueError('tile_size must be an integer ' 'or a pair of integers') assert_instance(tile_width, numbers.Number, 'tile_width of tile_size') assert_instance(tile_height, numbers.Number, 'tile_height of tile_size') self.tile_size = tile_width, tile_height self.time_range = None if time_range is not None: assert_true(len(time_range) == 2, 'time_range is invalid') self.time_range = tuple(time_range) self.time_period = None if time_period is not None: assert_instance(time_period, str, 'time_period') self.time_period = time_period self.chunks = None if chunks is not None: assert_instance(chunks, collections.Mapping, 'chunks') for chunk_dim, chunk_size in chunks.items(): assert_instance(chunk_dim, str, 'chunk dimension') assert_instance(chunk_size, (int, type(None)), 'chunk size') self.chunks = dict(chunks) self.metadata = None if metadata is not None: assert_instance(metadata, collections.Mapping, 'metadata') self.metadata = dict(metadata) self.variable_metadata = None if variable_metadata is not None: assert_instance(variable_metadata, collections.Mapping, 'variable_metadata') for var_name, metadata in variable_metadata.items(): assert_instance(var_name, str, 'chunk dimension') assert_instance(metadata, collections.Mapping, 'variable metadata') self.variable_metadata = dict(variable_metadata)