def get_legend(ctx: ServiceContext, ds_id: str, var_name: str, params: RequestParams): cmap_name = params.get_query_argument('cbar', default=None) cmap_vmin = params.get_query_argument_float('vmin', default=None) cmap_vmax = params.get_query_argument_float('vmax', default=None) cmap_w = params.get_query_argument_int('width', default=None) cmap_h = params.get_query_argument_int('height', default=None) if cmap_name is None or cmap_vmin is None or cmap_vmax is None or cmap_w is None or cmap_h is None: default_cmap_cbar, (default_cmap_vmin, default_cmap_vmax) = ctx.get_color_mapping( ds_id, var_name) cmap_name = cmap_name or default_cmap_cbar cmap_vmin = cmap_vmin or default_cmap_vmin cmap_vmax = cmap_vmax or default_cmap_vmax cmap_w = cmap_w or DEFAULT_CMAP_WIDTH cmap_h = cmap_h or DEFAULT_CMAP_HEIGHT try: _, cmap = get_cmap(cmap_name) except ValueError: raise ServiceResourceNotFoundError( f"color bar {cmap_name!r} not found") fig = matplotlib.figure.Figure(figsize=(cmap_w, cmap_h)) ax1 = fig.add_subplot(1, 1, 1) if '.cpd' in cmap_name: norm, ticks = get_norm(cmap_name) else: norm = matplotlib.colors.Normalize(vmin=cmap_vmin, vmax=cmap_vmax) ticks = None image_legend = matplotlib.colorbar.ColorbarBase(ax1, format='%.1f', ticks=ticks, cmap=cmap, norm=norm, orientation='vertical') image_legend_label = ctx.get_legend_label(ds_id, var_name) if image_legend_label is not None: image_legend.set_label(image_legend_label) fig.patch.set_facecolor('white') fig.patch.set_alpha(0.0) fig.tight_layout() buffer = io.BytesIO() fig.savefig(buffer, format='png') return buffer.getvalue()
def get_dataset_tile(ctx: ServiceContext, ds_id: str, var_name: str, x: str, y: str, z: str, params: RequestParams): x = RequestParams.to_int('x', x) y = RequestParams.to_int('y', y) z = RequestParams.to_int('z', z) tile_comp_mode = params.get_query_argument_int('mode', ctx.tile_comp_mode) trace_perf = params.get_query_argument_int('debug', ctx.trace_perf) != 0 cmap_name = params.get_query_argument('cbar', default=None) cmap_vmin = params.get_query_argument_float('vmin', default=None) cmap_vmax = params.get_query_argument_float('vmax', default=None) if cmap_name is None or cmap_vmin is None or cmap_vmax is None: default_cmap_name, default_cmap_vmin, default_cmap_vmax = ctx.get_color_mapping( ds_id, var_name) cmap_name = cmap_name or default_cmap_name cmap_vmin = cmap_vmin or default_cmap_vmin cmap_vmax = cmap_vmax or default_cmap_vmax ml_dataset = ctx.get_ml_dataset(ds_id) var = ml_dataset.base_dataset[var_name] labels = parse_non_spatial_labels(params.get_query_arguments(), var.dims, var.coords, allow_slices=False, exception_type=ServiceBadRequestError) return get_ml_dataset_tile(ml_dataset, var_name, x, y, z, labels=labels, cmap_name=cmap_name, cmap_vmin=cmap_vmin, cmap_vmax=cmap_vmax, image_cache=ctx.image_cache, tile_cache=ctx.tile_cache, tile_comp_mode=tile_comp_mode, trace_perf=trace_perf, exception_type=ServiceBadRequestError)
def get_var_indexers(cls, ds_name: str, var_name: str, var: xr.DataArray, dim_names: List[str], params: RequestParams) -> Dict[str, Any]: var_indexers = dict() for dim_name in dim_names: if dim_name not in var.coords: raise ServiceBadRequestError( f'dimension {dim_name!r} of variable {var_name!r} of dataset {ds_name!r} has no coordinates' ) coord_var = var.coords[dim_name] dim_value_str = params.get_query_argument(dim_name, None) try: if dim_value_str is None: var_indexers[dim_name] = coord_var.values[0] elif dim_value_str == 'current': var_indexers[dim_name] = coord_var.values[-1] elif np.issubdtype(coord_var.dtype, np.floating): var_indexers[dim_name] = float(dim_value_str) elif np.issubdtype(coord_var.dtype, np.integer): var_indexers[dim_name] = int(dim_value_str) elif np.issubdtype(coord_var.dtype, np.datetime64): if '/' in dim_value_str: date_str_1, date_str_2 = dim_value_str.split( '/', maxsplit=1) var_indexer_1 = pd.to_datetime(date_str_1) var_indexer_2 = pd.to_datetime(date_str_2) var_indexers[dim_name] = var_indexer_1 + ( var_indexer_2 - var_indexer_1) / 2 else: date_str = dim_value_str var_indexers[dim_name] = pd.to_datetime(date_str) else: raise ValueError( f'unable to convert value {dim_value_str!r} to {coord_var.dtype!r}' ) except ValueError as e: raise ServiceBadRequestError( f'{dim_value_str!r} is not a valid value for dimension {dim_name!r} ' f'of variable {var_name!r} of dataset {ds_name!r}') from e return var_indexers
def get_dataset_tile(ctx: ServiceContext, ds_id: str, var_name: str, x: str, y: str, z: str, params: RequestParams): x = RequestParams.to_int('x', x) y = RequestParams.to_int('y', y) z = RequestParams.to_int('z', z) tile_comp_mode = params.get_query_argument_int('mode', ctx.tile_comp_mode) trace_perf = params.get_query_argument_int('debug', ctx.trace_perf) != 0 ml_dataset = ctx.get_ml_dataset(ds_id) if var_name == 'rgb': norm_vmin = params.get_query_argument_float('vmin', default=0.0) norm_vmax = params.get_query_argument_float('vmax', default=1.0) var_names, norm_ranges = ctx.get_rgb_color_mapping( ds_id, norm_range=(norm_vmin, norm_vmax)) components = ('r', 'g', 'b') for i in range(3): c = components[i] var_names[i] = params.get_query_argument(c, default=var_names[i]) norm_ranges[i] = params.get_query_argument_float(f'{c}vmin', default=norm_ranges[i][0]), \ params.get_query_argument_float(f'{c}vmax', default=norm_ranges[i][1]) cmap_name = tuple(var_names) cmap_range = tuple(norm_ranges) for name in var_names: if name and name not in ml_dataset.base_dataset: raise ServiceBadRequestError( f'Variable {name!r} not found in dataset {ds_id!r}') var = None for name in var_names: if name and name in ml_dataset.base_dataset: var = ml_dataset.base_dataset[name] break if var is None: raise ServiceBadRequestError( f'No variable in dataset {ds_id!r} specified for RGB') else: cmap_name = params.get_query_argument('cbar', default=None) cmap_vmin = params.get_query_argument_float('vmin', default=None) cmap_vmax = params.get_query_argument_float('vmax', default=None) if cmap_name is None or cmap_vmin is None or cmap_vmax is None: default_cmap_name, (default_cmap_vmin, default_cmap_vmax) = ctx.get_color_mapping( ds_id, var_name) cmap_name = cmap_name or default_cmap_name cmap_vmin = cmap_vmin or default_cmap_vmin cmap_vmax = cmap_vmax or default_cmap_vmax cmap_range = cmap_vmin, cmap_vmax if var_name not in ml_dataset.base_dataset: raise ServiceBadRequestError( f'Variable {var_name!r} not found in dataset {ds_id!r}') var = ml_dataset.base_dataset[var_name] labels = parse_non_spatial_labels(params.get_query_arguments(), var.dims, var.coords, allow_slices=False, exception_type=ServiceBadRequestError) return get_ml_dataset_tile(ml_dataset, var_name, x, y, z, labels=labels, cmap_name=cmap_name, cmap_range=cmap_range, image_cache=ctx.image_cache, tile_cache=ctx.tile_cache, tile_comp_mode=tile_comp_mode, trace_perf=trace_perf, exception_type=ServiceBadRequestError)
def get_dataset_tile(ctx: ServiceContext, ds_id: str, var_name: str, x: str, y: str, z: str, params: RequestParams): x = RequestParams.to_int('x', x) y = RequestParams.to_int('y', y) z = RequestParams.to_int('z', z) tile_comp_mode = params.get_query_argument_int('mode', ctx.tile_comp_mode) trace_perf = params.get_query_argument_int('debug', ctx.trace_perf) != 0 measure_time = measure_time_cm(logger=_LOG, disabled=not trace_perf) var = ctx.get_variable_for_z(ds_id, var_name, z) dim_names = list(var.dims) if 'lon' not in dim_names or 'lat' not in dim_names: raise ServiceBadRequestError( f'Variable "{var_name}" of dataset "{ds_id}" is not geo-spatial') dim_names.remove('lon') dim_names.remove('lat') var_indexers = ctx.get_var_indexers(ds_id, var_name, var, dim_names, params) cmap_cbar = params.get_query_argument('cbar', default=None) cmap_vmin = params.get_query_argument_float('vmin', default=None) cmap_vmax = params.get_query_argument_float('vmax', default=None) if cmap_cbar is None or cmap_vmin is None or cmap_vmax is None: default_cmap_cbar, default_cmap_vmin, default_cmap_vmax = ctx.get_color_mapping( ds_id, var_name) cmap_cbar = cmap_cbar or default_cmap_cbar cmap_vmin = cmap_vmin or default_cmap_vmin cmap_vmax = cmap_vmax or default_cmap_vmax image_id = '-'.join( map(str, [ds_id, z, var_name, cmap_cbar, cmap_vmin, cmap_vmax] + [ f'{dim_name}={dim_value}' for dim_name, dim_value in var_indexers.items() ])) if image_id in ctx.image_cache: image = ctx.image_cache[image_id] else: no_data_value = var.attrs.get('_FillValue') valid_range = var.attrs.get('valid_range') if valid_range is None: valid_min = var.attrs.get('valid_min') valid_max = var.attrs.get('valid_max') if valid_min is not None and valid_max is not None: valid_range = [valid_min, valid_max] # Make sure we work with 2D image arrays only if var.ndim == 2: assert len(var_indexers) == 0 array = var elif var.ndim > 2: assert len(var_indexers) == var.ndim - 2 array = var.sel(method='nearest', **var_indexers) else: raise ServiceBadRequestError( f'Variable "{var_name}" of dataset "{var_name}" ' 'must be an N-D Dataset with N >= 2, ' f'but "{var_name}" is only {var.ndim}-D') cmap_vmin = np.nanmin( array.values) if np.isnan(cmap_vmin) else cmap_vmin cmap_vmax = np.nanmax( array.values) if np.isnan(cmap_vmax) else cmap_vmax tile_grid = ctx.get_tile_grid(ds_id) if not tile_comp_mode: image = NdarrayImage( array, image_id=f'ndai-{image_id}', tile_size=tile_grid.tile_size, # tile_cache=ctx.tile_cache, trace_perf=trace_perf) image = TransformArrayImage( image, image_id=f'tai-{image_id}', flip_y=tile_grid.inv_y, force_masked=True, no_data_value=no_data_value, valid_range=valid_range, # tile_cache=ctx.tile_cache, trace_perf=trace_perf) image = ColorMappedRgbaImage(image, image_id=f'rgb-{image_id}', value_range=(cmap_vmin, cmap_vmax), cmap_name=cmap_cbar, encode=True, format='PNG', tile_cache=ctx.tile_cache, trace_perf=trace_perf) else: image = ColorMappedRgbaImage2(array, image_id=f'rgb-{image_id}', tile_size=tile_grid.tile_size, cmap_range=(cmap_vmin, cmap_vmax), cmap_name=cmap_cbar, encode=True, format='PNG', flip_y=tile_grid.inv_y, no_data_value=no_data_value, valid_range=valid_range, tile_cache=ctx.tile_cache, trace_perf=trace_perf) ctx.image_cache[image_id] = image if trace_perf: _LOG.info( f'Created tiled image {image_id!r} of size {image.size} with tile grid:' ) _LOG.info(f' num_levels: {tile_grid.num_levels}') _LOG.info(f' num_level_zero_tiles: {tile_grid.num_tiles(0)}') _LOG.info(f' tile_size: {tile_grid.tile_size}') _LOG.info(f' geo_extent: {tile_grid.geo_extent}') _LOG.info(f' inv_y: {tile_grid.inv_y}') if trace_perf: _LOG.info(f'>>> tile {image_id}/{z}/{y}/{x}') with measure_time() as measured_time: tile = image.get_tile(x, y) if trace_perf: _LOG.info(f'<<< tile {image_id}/{z}/{y}/{x}: took ' + '%.2f seconds' % measured_time.duration) return tile