Пример #1
0
def open_data(url):
    """
    Opens a Catmaid URL, and returns an AcquisitionData instance
    url (string): URL where the Catmaid instance is hosted. Project id and stack id can be added to the URL by appending
        ?pid=1&sid0=1 , if this left out the first available project id and stack id are used. The URL should start
        with catmaid:// or catmaids:// for http and https protocols respectively.
    return (AcquisitionData): an opened Catmaid instance
    """
    if any(url.startswith(p) for p in PREFIXES):
        url = re.sub(r"catmaid([s]?)://", r"http\1://", url, 1)
    else:
        raise IOError("URL should start with catmaid:// or catmaids://")
    urlo = urlparse(url)
    parameters = parse_qs(urlo.query)
    base_url = '{uri.scheme}://{uri.netloc}{uri.path}'.format(
        uri=urlo).rstrip("/")
    project_id = int(
        parameters["pid"][0]) if "pid" in parameters.keys() else None
    stack_id = int(
        parameters["sid0"][0]) if "sid0" in parameters.keys() else None

    if project_id is None or stack_id is None:
        try:
            token, _, _ = read_config_file(base_url, token=True)
            auth = CatmaidApiTokenAuth(token) if token else None
            project_url = "{url}/projects/".format(url=base_url)
            response = requests.get(project_url, auth=auth)
            if response.status_code == 401:
                raise AuthenticationError(
                    "Wrong token while getting project info at {}".format(
                        project_url))
            else:
                response.raise_for_status()
            project_info = response.json()
            if project_info == [] and token is None:
                raise AuthenticationError(
                    "No project at {}, this Catmaid instance does not contain projects"
                    "or a token should have been provided.".format(
                        project_url))
            project_id = project_info[0][
                "id"] if project_id is None else project_id
            # loop through the projects to get the info of the project matching the project id.
            project = [p for p in project_info if p["id"] == project_id]
            stack_id = project[0]["stacks"][0][
                "id"] if stack_id is None else stack_id
        except Exception:
            # Try with project id and stack id is 1 if the project info cannot be accessed.
            project_id = 1 if project_id is None else project_id
            stack_id = 1 if stack_id is None else stack_id
        logging.info(
            "Project id and/or stack id not entered, using project {} and stack {}."
            .format(project_id, stack_id))
    return AcquisitionDataCatmaid(base_url, project_id, stack_id)
Пример #2
0
def get_stack_info(base_url, project_id, stack_id):
    """Get the stack info for a project hosted at the base url."""
    token, _, _ = read_config_file(base_url, token=True)
    stack_url = STACK_URL.format(base_url=base_url,
                                 project_id=project_id,
                                 stack_id=stack_id)
    auth = CatmaidApiTokenAuth(token) if token else None
    response = requests.get(stack_url, auth=auth)
    # A PermissionError is raised when authentication fails.
    if response.status_code == 404:
        raise ValueError(
            "no stack info at this url, check the base url {base_url}".format(
                base_url=base_url))
    elif "PermissionError" in response.text:
        raise AuthenticationError(
            "Failed authentication getting stack info at {stack_url}".format(
                stack_url=stack_url))
    elif "DoesNotExist" in response.text:
        # Catmaid returns a 200 code with an error text field, when there's no stack info at that url.
        raise ValueError(
            "No stack info at this url {stack_url}, check project id {project_id} and stack id {stack_id}"
            .format(stack_url=stack_url,
                    project_id=project_id,
                    stack_id=stack_id))
    stack_info = response.json()
    return stack_info
Пример #3
0
    def getTile(self, x, y, zoom, depth=0):
        """
        Fetches one tile
        x (0<=int): X index of the tile.
        y (0<=int): Y index of the tile
        zoom (0<=int): zoom level to use. The total shape of the image is shape / 2**zoom.
            The number of tiles available in an image is ceil((shape//zoom)/tile_shape)
        depth (0<=int): The Z index of the stack.
        return:
            tile (DataArray): tile containing the image data and the relevant metadata.
        """
        tile_width, tile_height = self.tile_shape
        tile_url = format_tile_url(
            tile_source_type=self._stack_info["mirrors"][0]
            ["tile_source_type"],
            image_base=self._stack_info["mirrors"][0]["image_base"],
            zoom=zoom,
            depth=depth,
            col=x,
            row=y,
            file_extension=self._file_extension,
            tile_width=tile_width,
            tile_height=tile_height,
        )
        try:
            image = response_to_array(
                self._session.get(tile_url, auth=self._auth))
        except HTTPError as e:
            if e.response.status_code == 401:
                raise AuthenticationError(
                    "Authentication failed while getting tiles at {}".format(
                        tile_url))
            else:
                logging.error("No tile at %s (error %s), returning blank tile",
                              tile_url, e.response.status_code)
                image = numpy.zeros((tile_width, tile_height),
                                    dtype=self.dtype)

        tile = model.DataArray(image, self.metadata.copy())
        orig_pixel_size = self.metadata.get(model.MD_PIXEL_SIZE, (1e-6, 1e-6))
        # calculate the pixel size of the tile for the zoom level
        tile_pixel_size = tuple(ps * 2**zoom for ps in orig_pixel_size)
        tile.metadata[model.MD_PIXEL_SIZE] = tile_pixel_size

        # calculate the center of the tile
        tile.metadata[model.MD_POS] = get_tile_md_pos((x, y), self.tile_shape,
                                                      tile, self)

        return tile