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)
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
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