def parse_region(
    in_image: Image, top: Size, left: Size, width: Size, height: Size, tier_idx: int = 0,
    tier_type: TierIndexType = TierIndexType.LEVEL, silent_oob: bool = False
) -> Region:
    """
    Parse a region

    Parameters
    ----------
    in_image
        Image in which region is extracted
    top
    left
    width
    height
    tier_idx
        Tier index to use as reference
    tier_type
        Type of tier index
    silent_oob
        Whether out of bounds region should raise an error or not.

    Returns
    -------
    region
        The parsed region

    Raises
    ------
    BadRequestException
        If a region coordinate is out of bound and silent_oob is False.
    """
    if tier_type == TierIndexType.ZOOM:
        check_zoom_validity(in_image.pyramid, tier_idx)
        ref_tier = in_image.pyramid.get_tier_at_zoom(tier_idx)
    else:
        check_level_validity(in_image.pyramid, tier_idx)
        ref_tier = in_image.pyramid.get_tier_at_level(tier_idx)

    if type(top) == float:
        top *= ref_tier.height
    if type(left) == float:
        left *= ref_tier.width
    if type(width) == float:
        width *= ref_tier.width
    if type(height) == float:
        height *= ref_tier.height

    downsample = (ref_tier.width_factor, ref_tier.height_factor)
    region = Region(top, left, width, height, downsample)

    if not silent_oob:
        clipped = copy(region).clip(ref_tier.width, ref_tier.height)
        if clipped != region:
            raise BadRequestException(
                detail=f"Some coordinates of region {region} are out of bounds."
            )

    return region
Exemple #2
0
def test_check_level_validity():
    with not_raises(BadRequestException):
        check_level_validity(FakeImagePyramid(100, 100, 1).pyramid, 0)
        check_level_validity(FakeImagePyramid(100, 100, 20).pyramid, 10)
        check_level_validity(FakeImagePyramid(100, 100, 20).pyramid, None)

    with pytest.raises(BadRequestException):
        check_level_validity(FakeImagePyramid(100, 100, 1).pyramid, 1)

    with pytest.raises(BadRequestException):
        check_level_validity(FakeImagePyramid(100, 100, 20).pyramid, 25)
Exemple #3
0
def _show_mask(
        request: Request,
        response: Response,  # required for @cache  # noqa
        path: Path,
        annotations,
        context_factor,
        height,
        width,
        length,
        zoom,
        level,
        extension,
        headers,
        config):
    in_image = path.get_spatial()
    check_representation_existence(in_image)

    annots = parse_annotations(ensure_list(annotations),
                               ignore_fields=['stroke_width', 'stroke_color'],
                               default={'fill_color': WHITE},
                               origin=headers.annot_origin,
                               im_height=in_image.height)

    region = get_annotation_region(in_image, annots, context_factor)

    out_format, mimetype = get_output_format(extension, headers.accept,
                                             PROCESSING_MIMETYPES)
    check_zoom_validity(in_image.pyramid, zoom)
    check_level_validity(in_image.pyramid, level)
    req_size = get_window_output_dimensions(in_image, region, height, width,
                                            length, zoom, level)
    out_size = safeguard_output_dimensions(headers.safe_mode,
                                           config.output_size_limit, *req_size)
    out_width, out_height = out_size

    affine = annotation_crop_affine_matrix(annots.region, region, out_width,
                                           out_height)

    return MaskResponse(in_image, annots, affine, out_width, out_height, 8,
                        out_format).http_response(
                            mimetype,
                            extra_headers=add_image_size_limit_header(
                                dict(), *req_size, *out_size))
Exemple #4
0
def _show_resized(
    request: Request, response: Response,  # required for @cache  # noqa
    path: Path,
    height, width, length, zoom, level,
    channels, z_slices, timepoints,
    min_intensities, max_intensities, filters, gammas, threshold,
    bits, colorspace,
    extension,
    headers,
    config: Settings,
    colormaps=None, c_reduction=ChannelReduction.ADD, z_reduction=None, t_reduction=None
):
    in_image = path.get_spatial()
    check_representation_existence(in_image)

    out_format, mimetype = get_output_format(extension, headers.accept, PROCESSING_MIMETYPES)
    check_zoom_validity(in_image.pyramid, zoom)
    check_level_validity(in_image.pyramid, level)
    req_size = get_thumb_output_dimensions(in_image, height, width, length, zoom, level)
    out_size = safeguard_output_dimensions(headers.safe_mode, config.output_size_limit, *req_size)
    out_width, out_height = out_size

    channels = ensure_list(channels)
    z_slices = ensure_list(z_slices)
    timepoints = ensure_list(timepoints)

    channels = get_channel_indexes(in_image, channels)
    check_reduction_validity(channels, c_reduction, 'channels')
    z_slices = get_zslice_indexes(in_image, z_slices)
    check_reduction_validity(z_slices, z_reduction, 'z_slices')
    timepoints = get_timepoint_indexes(in_image, timepoints)
    check_reduction_validity(timepoints, t_reduction, 'timepoints')

    min_intensities = ensure_list(min_intensities)
    max_intensities = ensure_list(max_intensities)
    colormaps = ensure_list(colormaps)
    filters = ensure_list(filters)
    gammas = ensure_list(gammas)

    array_parameters = ('min_intensities', 'max_intensities', 'colormaps', 'gammas')
    check_array_size_parameters(
        array_parameters, locals(), allowed=[0, 1, len(channels)], nullable=False
    )
    intensities = parse_intensity_bounds(
        in_image, channels, z_slices, timepoints, min_intensities, max_intensities
    )
    min_intensities, max_intensities = intensities
    colormaps = parse_colormap_ids(colormaps, ALL_COLORMAPS, channels, in_image.channels)

    array_parameters = ('filters',)
    check_array_size_parameters(
        array_parameters, locals(), allowed=[0, 1], nullable=False
    )
    filters = parse_filter_ids(filters, FILTERS)

    out_bitdepth = parse_bitdepth(in_image, bits)

    return ResizedResponse(
        in_image, channels, z_slices, timepoints,
        out_format, out_width, out_height,
        c_reduction, z_reduction, t_reduction,
        gammas, filters, colormaps, min_intensities, max_intensities,
        False, out_bitdepth, threshold, colorspace
    ).http_response(
        mimetype,
        extra_headers=add_image_size_limit_header(dict(), *req_size, *out_size)
    )
Exemple #5
0
def _show_window(
    request: Request, response: Response,  # required for @cache  # noqa
    path: Path,
    region: Union[Region, dict],
    height, width, length, zoom, level,
    channels, z_slices, timepoints,
    min_intensities, max_intensities, filters, gammas, threshold,
    bits, colorspace,
    annotations: Union[ParsedAnnotations, dict, List[dict]],
    annotation_style: dict,
    extension,
    headers,
    config: Settings,
    colormaps=None, c_reduction=ChannelReduction.ADD, z_reduction=None, t_reduction=None
):
    in_image = path.get_spatial()
    check_representation_existence(in_image)

    if not isinstance(region, Region):
        tier_index_type = region['tier_index_type']
        reference_tier_index = region['reference_tier_index']
        if reference_tier_index is None:
            if tier_index_type == TierIndexType.LEVEL:
                reference_tier_index = 0
            else:
                reference_tier_index = in_image.pyramid.max_zoom

        if 'top' in region:
            # Parse raw WindowRegion to Region
            region = parse_region(
                in_image, region['top'], region['left'],
                region['width'], region['height'],
                reference_tier_index, tier_index_type,
                silent_oob=False
            )
        elif 'ti' in region:
            # Parse raw WindowTileIndex region to Region
            check_tileindex_validity(
                in_image.pyramid, region['ti'],
                reference_tier_index, tier_index_type
            )
            region = in_image.pyramid.get_tier_at(
                reference_tier_index,
                tier_index_type
            ).get_ti_tile(region['ti'])
        elif ('tx', 'ty') in region:
            # Parse raw WindowTileCoord region to Region
            check_tilecoord_validity(
                in_image.pyramid, region['tx'], region['ty'],
                reference_tier_index, tier_index_type
            )
            region = in_image.pyramid.get_tier_at(
                reference_tier_index,
                tier_index_type
            ).get_txty_tile(region['tx'], region['ty'])

    out_format, mimetype = get_output_format(extension, headers.accept, VISUALISATION_MIMETYPES)
    check_zoom_validity(in_image.pyramid, zoom)
    check_level_validity(in_image.pyramid, level)
    req_size = get_window_output_dimensions(in_image, region, height, width, length, zoom, level)
    out_size = safeguard_output_dimensions(headers.safe_mode, config.output_size_limit, *req_size)
    out_width, out_height = out_size

    channels = ensure_list(channels)
    z_slices = ensure_list(z_slices)
    timepoints = ensure_list(timepoints)

    channels = get_channel_indexes(in_image, channels)
    check_reduction_validity(channels, c_reduction, 'channels')
    z_slices = get_zslice_indexes(in_image, z_slices)
    check_reduction_validity(z_slices, z_reduction, 'z_slices')
    timepoints = get_timepoint_indexes(in_image, timepoints)
    check_reduction_validity(timepoints, t_reduction, 'timepoints')

    min_intensities = ensure_list(min_intensities)
    max_intensities = ensure_list(max_intensities)
    colormaps = ensure_list(colormaps)
    filters = ensure_list(filters)
    gammas = ensure_list(gammas)

    array_parameters = ('min_intensities', 'max_intensities', 'colormaps', 'gammas')
    check_array_size_parameters(
        array_parameters, locals(), allowed=[0, 1, len(channels)], nullable=False
    )
    intensities = parse_intensity_bounds(
        in_image, channels, z_slices, timepoints, min_intensities, max_intensities
    )
    min_intensities, max_intensities = intensities
    colormaps = parse_colormap_ids(colormaps, ALL_COLORMAPS, channels, in_image.channels)

    array_parameters = ('filters',)
    check_array_size_parameters(
        array_parameters, locals(), allowed=[0, 1], nullable=False
    )
    filters = parse_filter_ids(filters, FILTERS)

    out_bitdepth = parse_bitdepth(in_image, bits)

    if annotations and annotation_style and not isinstance(annotations, ParsedAnnotations):
        if annotation_style['mode'] == AnnotationStyleMode.DRAWING:
            ignore_fields = ['fill_color']
            default = {'stroke_color': RED, 'stroke_width': 1}
            point_envelope_length = annotation_style['point_envelope_length']
        else:
            ignore_fields = ['stroke_width', 'stroke_color']
            default = {'fill_color': WHITE}
            point_envelope_length = None

        annotations = parse_annotations(
            ensure_list(annotations), ignore_fields,
            default, point_envelope_length,
            origin=headers.annot_origin, im_height=in_image.height
        )

    affine = None
    if annotations:
        affine = annotation_crop_affine_matrix(annotations.region, region, *out_size)

    if annotations and annotation_style and \
            annotation_style['mode'] == AnnotationStyleMode.MASK:
        window = MaskResponse(
            in_image,
            annotations, affine,
            out_width, out_height, out_bitdepth, out_format
        )
    else:
        window = WindowResponse(
            in_image, channels, z_slices, timepoints,
            region, out_format, out_width, out_height,
            c_reduction, z_reduction, t_reduction,
            gammas, filters, colormaps,
            min_intensities, max_intensities, False,
            out_bitdepth, threshold, colorspace,
            annotations, affine, annotation_style
        )

    return window.http_response(
        mimetype,
        extra_headers=add_image_size_limit_header(dict(), *req_size, *out_size)
    )