Esempio n. 1
0
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()
Esempio n. 2
0
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)
Esempio n. 3
0
 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
Esempio n. 4
0
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)
Esempio n. 5
0
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