Пример #1
0
    def _boss_cutout(self, requested_bbox, steps, channel_slice=slice(None)):
        bounds = Bbox.clamp(requested_bbox, self.bounds)

        if bounds.volume() < 1:
            raise ValueError(
                'Requested less than one pixel of volume. {}'.format(bounds))

        x_rng = [bounds.minpt.x, bounds.maxpt.x]
        y_rng = [bounds.minpt.y, bounds.maxpt.y]
        z_rng = [bounds.minpt.z, bounds.maxpt.z]

        layer_type = 'image' if self.layer_type == 'unknown' else self.layer_type

        chan = ChannelResource(
            collection_name=self.path.bucket,
            experiment_name=self.path.dataset,
            name=self.path.layer,  # Channel
            type=layer_type,
            datatype=self.dtype,
        )

        rmt = BossRemote(boss_credentials)
        cutout = rmt.get_cutout(chan,
                                self.mip,
                                x_rng,
                                y_rng,
                                z_rng,
                                no_cache=True)
        cutout = cutout.T
        cutout = cutout.astype(self.dtype)
        cutout = cutout[::steps.x, ::steps.y, ::steps.z]

        if len(cutout.shape) == 3:
            cutout = cutout.reshape(tuple(list(cutout.shape) + [1]))

        if self.bounded or self.autocrop or bounds == requested_bbox:
            return VolumeCutout.from_volume(self, cutout, bounds)

        # This section below covers the case where the requested volume is bigger
        # than the dataset volume and the bounds guards have been switched
        # off. This is useful for Marching Cubes where a 1px excess boundary
        # is needed.
        shape = list(requested_bbox.size3()) + [cutout.shape[3]]
        renderbuffer = np.zeros(shape=shape, dtype=self.dtype, order='F')
        txrx.shade(renderbuffer, requested_bbox, cutout, bounds)
        return VolumeCutout.from_volume(self, renderbuffer, requested_bbox)
Пример #2
0
 def __init__(self, host, token, collection, experiment, chanList):
     self._collection = collection
     self._experiment = experiment
     self._bossRemote = BossRemote({'protocol':'https',
                                    'host':host,
                                    'token':token})
     self._chanList = {}
     for chanDict in chanList:
         try:
             self._chanList[chanDict['name']] = ChannelResource(chanDict['name'],
                                                                collection,
                                                                experiment,
                                                                'image',
                                                                datatype=chanDict['dtype'])
         except:
             #TODO error handle here
             raise Exception("Failed to load")
             sys.exit(1)
Пример #3
0
def setup_channel_boss(remote,
                       collection,
                       experiment,
                       channel,
                       channel_type='image',
                       datatype='uint16'):
    (exp_setup, coord_actual) = setup_experiment_boss(remote, collection,
                                                      experiment)

    chan_setup = ChannelResource(channel,
                                 collection,
                                 experiment,
                                 channel_type,
                                 datatype=datatype)
    try:
        chan_actual = remote.get_project(chan_setup)
        return (exp_setup, coord_actual, chan_actual)
    except Exception as e:
        print(e.message)
Пример #4
0
    def upload(self, image, offset, mip):
        shape = Vec(*image.shape[:3])
        offset = Vec(*offset)

        bounds = Bbox(offset, shape + offset)

        if bounds.subvoxel():
            raise exceptions.EmptyRequestException(
                'Requested less than one pixel of volume. {}'.format(bounds))

        if self.autocrop:
            image, bounds = autocropfn(self.meta, image, bounds, mip)
            offset = bounds.minpt

        check_grid_aligned(self.meta,
                           image,
                           bounds,
                           mip,
                           throw_error=(self.non_aligned_writes == False))

        x_rng = [bounds.minpt.x, bounds.maxpt.x]
        y_rng = [bounds.minpt.y, bounds.maxpt.y]
        z_rng = [bounds.minpt.z, bounds.maxpt.z]

        layer_type = 'image' if self.layer_type == 'unknown' else self.meta.layer_type

        chan = ChannelResource(
            collection_name=self.meta.path.bucket,
            experiment_name=self.meta.path.dataset,
            name=self.meta.path.layer,  # Channel
            type=layer_type,
            datatype=self.meta.data_type,
        )

        if image.shape[3] == 1:
            image = image.reshape(image.shape[:3])

        rmt = BossRemote(boss_credentials)
        image = image.T
        image = np.asfortranarray(image.astype(self.meta.dtype))

        rmt.create_cutout(chan, mip, x_rng, y_rng, z_rng, image)
Пример #5
0
def create_channel_resource(rmt,
                            chan_name,
                            coll_name,
                            exp_name,
                            type='image',
                            base_resolution=0,
                            sources=[],
                            datatype='uint16',
                            new_channel=True):
    channel_resource = ChannelResource(chan_name,
                                       coll_name,
                                       exp_name,
                                       type=type,
                                       base_resolution=base_resolution,
                                       sources=sources,
                                       datatype=datatype)
    if new_channel:
        new_rsc = rmt.create_project(channel_resource)
        return new_rsc

    return channel_resource
Пример #6
0
 def __init__(self,
              resource: Union[BossResource, str],
              remote: BossRemote = None):
     self._remote = remote or BossRemote(_DEFAULT_BOSS_OPTIONS)
     if isinstance(resource, str):
         resource = resource.split("://")[-1]
         path_items = resource.split("/")
         if len(path_items) == 1:
             self._resource = self._remote.get_project(
                 CollectionResource(path_items[0]))
         elif len(path_items) == 2:
             self._resource = self._remote.get_project(
                 ExperimentResource(path_items[1], path_items[0]))
         elif len(path_items) == 3:
             self._resource = self._remote.get_project(
                 ChannelResource(path_items[2], path_items[0],
                                 path_items[1]))
         else:
             raise ValueError(f"Invalid resource path: {resource}")
     else:
         self._resource = resource
Пример #7
0
class BaseVersionTest(unittest.TestCase):
    def setUp(self):
        self.resource = CollectionResource('coll1')
        self.chanResource = ChannelResource(
            'chan1', 'coll1', 'exp1', 'image', 'null descr', 0, 'uint8', 0)
        self.annoResource = ChannelResource(
            'annChan', 'coll1', 'exp1', 'annotation', 'null descr',
            0, 'uint64', 0, sources=['chan1'])
        self.test_project = ProjectImpl()
        self.test_meta = MetadataImpl()
        self.test_volume = VolumeImpl()
        self.url_prefix = 'https://api.theboss.io'

    ##
    ## Methods used for the project service.
    ##

    def test_build_url_for_list(self):
        """A list operation's URL is different than any other operation.  It
        uses the plural form of the resource's type name rather than the
        resource's name.
        """
        actual = self.test_project.build_url(
            self.resource, self.url_prefix, 'collection', req_type='list')
        self.assertEqual(
            self.url_prefix + '/' + self.test_project.version + '/' +
            self.test_project.endpoint + '/' + self.resource.name + '/',
            actual)

    def test_build_url_for_cutout(self):
        """Cutout URLs are also different than standard operations."""
        actual = self.test_project.build_url(
            self.chanResource, self.url_prefix, 'cutout', req_type='cutout')
        coll = self.chanResource.coll_name
        exp = self.chanResource.exp_name
        chan = self.chanResource.name
        self.assertEqual(
            self.url_prefix + '/' + self.test_project.version + '/' +
            'cutout/' + coll + '/' + exp + '/' + chan,
            actual)

    def test_build_url_for_cutout_to_black(self):
        """
        Test cutout to black URL
        """
        actual = self.test_project.build_url(
        self.chanResource, self.url_prefix, 'cutout/to_black', req_type='cutout')
        coll = self.chanResource.coll_name
        exp = self.chanResource.exp_name
        chan = self.chanResource.name
        expected = "/".join(
            [
                self.url_prefix,
                self.test_project.version,
                "cutout/to_black",
                coll,
                exp,
                chan,
            ]
        )

        self.assertEqual(expected, actual)

    def test_build_url_normal(self):
        """Test standard use of BaseVersion.build_url().
        """
        actual = self.test_project.build_url(
            self.resource, self.url_prefix, 'collection', req_type='normal')
        self.assertEqual(
            self.url_prefix + '/' + self.test_project.version + '/' +
            self.test_project.endpoint + '/' + self.resource.name,
            actual)

    def test_get_headers_gives_dict_with_content_type(self):
        actual = self.test_project.get_headers('application/json', 'my_token')
        self.assertTrue('Content-Type' in actual)
        self.assertEqual('application/json', actual['Content-Type'])

    def test_get_headers_gives_dict_with_authorization(self):
        actual = self.test_project.get_headers('application/json', 'my_token')
        self.assertTrue('Authorization' in actual)
        self.assertEqual('Token my_token', actual['Authorization'])

    def test_get_request(self):
        url_prefix = 'https://api.theboss.io'
        token = 'foobar'
        actual = self.test_project.get_request(
            self.resource, 'GET', 'application/json', url_prefix, token,
            proj_list_req=False)
        self.assertEqual(
            '{}/{}/{}/{}'.format(url_prefix, self.test_project.version, self.test_project.endpoint, self.resource.name),
            actual.url)
        self.assertEqual('Token {}'.format(token), actual.headers['Authorization'])
        self.assertEqual('application/json', actual.headers['Content-Type'])

    def test_get_group_request(self):
        url_prefix = 'https://api.theboss.io'
        token = 'foobar'
        grp_name = 'fire'

        expected = '{}/{}/groups/{}/'.format(
            url_prefix, self.test_project.version, grp_name)

        actual = self.test_project.get_group_request(
            'GET', 'application/json', url_prefix, token, grp_name)

        self.assertEqual(expected, actual.url)

    def test_get_permission_request(self):
        url_prefix = 'https://api.theboss.io'
        token = 'foobar'
        grp_name = 'fire'
        post_data = {"group": grp_name,
                     "permissions": ['update', 'add', 'delete'],
                     }
        post_data.update(self.chanResource.get_dict_route())

        expected = '{}/{}/permissions/'.format(url_prefix, self.test_volume.version)

        actual = self.test_project.get_permission_request(
            'GET', 'application/json', url_prefix, token, post_data=post_data)

        self.assertEqual(expected, actual.url)

    def test_get_user_role_request(self):
        url_prefix = 'https://api.theboss.io'
        token = 'foobar'
        user = '******'
        role = 'admin'

        expected = '{}/{}/sso/user-role/{}/{}'.format(
            url_prefix, self.test_project.version, user, role)

        actual = self.test_project.get_user_role_request(
            'POST', 'application/json', url_prefix, token, user, role)

        self.assertEqual(expected, actual.url)

    def test_get_user_role_request_no_role(self):
        url_prefix = 'https://api.theboss.io'
        token = 'foobar'
        user = '******'

        expected = '{}/{}/sso/user-role/{}'.format(
            url_prefix, self.test_project.version, user)

        actual = self.test_project.get_user_role_request(
            'POST', 'application/json', url_prefix, token, user)

        self.assertEqual(expected, actual.url)

    def test_get_user_request_just_username(self):
        url_prefix = 'https://api.theboss.io'
        token = 'foobar'
        user = '******'

        expected = '{}/{}/sso/user/{}'.format(
            url_prefix, self.test_project.version, user)

        actual = self.test_project.get_user_request(
            'POST', 'application/json', url_prefix, token, user)

        self.assertEqual(expected, actual.url)

    def test_get_user_request_with_firstname(self):
        url_prefix = 'https://api.theboss.io'
        token = 'foobar'
        user = '******'
        first = 'Roger'

        expected = '{}/{}/sso/user/{}'.format(
            url_prefix, self.test_project.version, user)

        expectedData = { 'first_name': first }

        actual = self.test_project.get_user_request(
            'POST', 'application/json', url_prefix, token, user, first)

        self.assertEqual(expected, actual.url)
        self.assertDictEqual(expectedData, actual.json)

    def test_get_user_request_with_lastname(self):
        url_prefix = 'https://api.theboss.io'
        token = 'foobar'
        user = '******'
        last = 'Roger'

        expected = '{}/{}/sso/user/{}'.format(
            url_prefix, self.test_project.version, user)

        expectedData = { 'last_name': last }

        actual = self.test_project.get_user_request(
            'POST', 'application/json', url_prefix, token, user, last_name=last)

        self.assertEqual(expected, actual.url)
        self.assertDictEqual(expectedData, actual.json)

    def test_get_user_request_with_email(self):
        url_prefix = 'https://api.theboss.io'
        token = 'foobar'
        user = '******'
        email = '*****@*****.**'

        expected = '{}/{}/sso/user/{}'.format(
            url_prefix, self.test_project.version, user)

        expectedData = { 'email': email }

        actual = self.test_project.get_user_request(
            'POST', 'application/json', url_prefix, token, user, email=email)

    def test_get_user_request_with_password_and_user(self):
        url_prefix = 'https://api.theboss.io'
        token = 'foobar'
        user = '******'
        password = '******'

        expected = '{}/{}/sso/user/{}'.format(
            url_prefix, self.test_project.version, user)

        expectedData = { 'password': password }

        actual = self.test_project.get_user_request(
            'POST', 'application/json', url_prefix, token, user, password=password)

        self.assertEqual(expected, actual.url)
        self.assertDictEqual(expectedData, actual.json)

    def test_get_user_request_with_password_and_email(self):
        url_prefix = 'https://api.theboss.io'
        token = 'foobar'
        user = '******'
        first = 'Roger'
        last = 'Dodger'
        email = '*****@*****.**'
        password = '******'

        expected = '{}/{}/sso/user/{}'.format(
            url_prefix, self.test_project.version, user)

        expectedData = {
            'first_name': first, 'last_name': last, 'email': email,
            'password': password }

        actual = self.test_project.get_user_request(
            'POST', 'application/json', url_prefix, token, user, first, last,
            email, password)

        self.assertEqual(expected, actual.url)
        self.assertDictEqual(expectedData, actual.json)

    ##
    ## Methods used for the metadata service.
    ##

    def test_build_metadata_url_no_value(self):
        key = 'foo'
        actual = self.test_meta.build_metadata_url(
            self.resource, self.url_prefix, key)
        self.assertEqual(
            self.url_prefix + '/' + self.test_meta.version + '/' +
            self.test_meta.endpoint + '/' + self.resource.name + '/?key=' + key,
            actual)

    def test_build_metadata_url_key_and_value(self):
        key = 'foo'
        value = 'bar'
        actual = self.test_meta.build_metadata_url(
            self.resource, self.url_prefix, key, value)
        self.assertEqual(
            self.url_prefix + '/' + self.test_meta.version + '/' +
            self.test_meta.endpoint + '/' + self.resource.name + '/?key=' +
            key + '&value=' + value,
            actual)

    def test_get_metadata_request(self):
        url_prefix = 'https://api.theboss.io'
        token = 'foobar'
        key = 'version'
        actual = self.test_meta.get_metadata_request(
            self.resource, 'GET', 'application/json', url_prefix, token, key)
        self.assertEqual(
            '{}/{}/{}/{}/?key={}'.format(url_prefix, self.test_meta.version,
             self.test_meta.endpoint, self.resource.name, key),
             actual.url)
        self.assertEqual('Token {}'.format(token), actual.headers['Authorization'])
        self.assertEqual('application/json', actual.headers['Content-Type'])

    ##
    ## Methods used for the volume service.
    ##

    def test_convert_int_list_range_to_str(self):
        exp = '2:7'
        actual = self.test_volume.convert_int_list_range_to_str([2,7])
        self.assertEqual(exp, actual)

    def test_convert_int_list_range_to_str_bad_range(self):
        with self.assertRaises(RuntimeError):
            self.test_volume.convert_int_list_range_to_str([7,5])

    def test_convert_int_list_range_to_str_wrong_number_of_elements(self):
        with self.assertRaises(RuntimeError):
            self.test_volume.convert_int_list_range_to_str([5, 7, 9])

    def test_convert_int_list_range_to_str_no_list(self):
        with self.assertRaises(RuntimeError):
            self.test_volume.convert_int_list_range_to_str('5, 7')

    def test_build_cutout_url_no_time_range(self):
        res = 0
        x_rng_lst = [20, 40]
        x_range = '20:40'
        y_rng_lst = [50, 70]
        y_range = '50:70'
        z_rng_lst = [30, 50]
        z_range = '30:50'
        t_rng_lst = None
        actual = self.test_volume.build_cutout_url(
            self.chanResource, self.url_prefix,
            res, x_rng_lst, y_rng_lst, z_rng_lst, t_rng_lst)

        self.assertEqual(
            self.url_prefix + '/' + self.test_volume.version + '/' + self.test_volume.endpoint +
            '/' + self.chanResource.coll_name + '/' + self.chanResource.exp_name +
            '/' + self.chanResource.name + '/' + str(res) + '/' + x_range + '/' +
            y_range + '/' + z_range + '/',
            actual)

    def test_build_cutout_to_black_url_no_time_range(self):
        res = 0
        x_rng_lst = [20, 40]
        x_range = '20:40'
        y_rng_lst = [50, 70]
        y_range = '50:70'
        z_rng_lst = [30, 50]
        z_range = '30:50'
        t_rng_lst = None
        actual = self.test_volume.build_cutout_to_black_url(
            self.chanResource, self.url_prefix,
            res, x_rng_lst, y_rng_lst, z_rng_lst, t_rng_lst)

        expected = '/'.join([
            self.url_prefix,
            self.test_volume.version,
            "cutout/to_black",
            self.chanResource.coll_name,
            self.chanResource.exp_name,
            self.chanResource.name,
            str(res),
            x_range,
            y_range,
            z_range,
        ]) + '/'

        self.assertEqual(expected, actual)

    def test_build_cutout_url_no_time_range_with_ids(self):
        res = 0
        x_rng_lst = [20, 40]
        x_range = '20:40'
        y_rng_lst = [50, 70]
        y_range = '50:70'
        z_rng_lst = [30, 50]
        z_range = '30:50'
        t_rng_lst = None
        id_list = [2, 7]
        id_list_str = '2,7'
        actual = self.test_volume.build_cutout_url(
            self.chanResource, self.url_prefix,
            res, x_rng_lst, y_rng_lst, z_rng_lst, t_rng_lst, id_list)

        self.assertEqual(
            self.url_prefix + '/' + self.test_volume.version + '/' + self.test_volume.endpoint +
            '/' + self.chanResource.coll_name + '/' + self.chanResource.exp_name +
            '/' + self.chanResource.name + '/' + str(res) + '/' + x_range + '/' +
            y_range + '/' + z_range + '/?filter=' + id_list_str,
            actual)

    def test_build_cutout_url_with_time_range(self):
        res = 0
        x_rng_lst = [20, 40]
        x_range = '20:40'
        y_rng_lst = [50, 70]
        y_range = '50:70'
        z_rng_lst = [30, 50]
        z_range = '30:50'
        t_rng_lst = [10, 25]
        time_range = '10:25'
        actual = self.test_volume.build_cutout_url(
            self.chanResource, self.url_prefix,
            res, x_rng_lst, y_rng_lst, z_rng_lst, t_rng_lst)

        self.assertEqual(
            self.url_prefix + '/' + self.test_volume.version + '/' + self.test_volume.endpoint +
            '/' + self.chanResource.coll_name + '/' + self.chanResource.exp_name +
            '/' + self.chanResource.name + '/' + str(res) + '/' + x_range + '/' +
            y_range + '/' + z_range + '/' + time_range + '/',
            actual)

    def test_build_cutout_to_black_url_with_time_range(self):
        res = 0
        x_rng_lst = [20, 40]
        x_range = '20:40'
        y_rng_lst = [50, 70]
        y_range = '50:70'
        z_rng_lst = [30, 50]
        z_range = '30:50'
        t_rng_lst = [10, 25]
        time_range = '10:25'
        actual = self.test_volume.build_cutout_to_black_url(
            self.chanResource, self.url_prefix,
            res, x_rng_lst, y_rng_lst, z_rng_lst, t_rng_lst)

        expected = '/'.join([
            self.url_prefix,
            self.test_volume.version,
            "cutout/to_black",
            self.chanResource.coll_name,
            self.chanResource.exp_name,
            self.chanResource.name,
            str(res),
            x_range,
            y_range,
            z_range,
            time_range,
        ]) + '/'

        self.assertEqual(expected, actual)

    def test_build_cutout_url_with_time_range_and_ids(self):
        res = 0
        x_rng_lst = [20, 40]
        x_range = '20:40'
        y_rng_lst = [50, 70]
        y_range = '50:70'
        z_rng_lst = [30, 50]
        z_range = '30:50'
        t_rng_lst = [10, 25]
        time_range = '10:25'
        id_list = [2, 7]
        id_list_str = '2,7'
        actual = self.test_volume.build_cutout_url(
            self.chanResource, self.url_prefix,
            res, x_rng_lst, y_rng_lst, z_rng_lst, t_rng_lst, id_list)

        self.assertEqual(
            self.url_prefix + '/' + self.test_volume.version + '/' + self.test_volume.endpoint +
            '/' + self.chanResource.coll_name + '/' + self.chanResource.exp_name +
            '/' + self.chanResource.name + '/' + str(res) + '/' + x_range + '/' +
            y_range + '/' + z_range + '/' + time_range + '/?filter=' + id_list_str,
            actual)

    def test_get_cutout_request(self):
        url_prefix = 'https://api.theboss.io'
        token = 'foobar'
        resolution = 0
        x_rng_lst = [20, 40]
        x_range = '20:40'
        y_rng_lst = [50, 70]
        y_range = '50:70'
        z_rng_lst = [30, 50]
        z_range = '30:50'
        t_rng_lst = [10, 25]
        time_range = '10:25'
        data = numpy.random.randint(0, 3000, (15, 20, 20, 20), numpy.uint16)

        actual = self.test_volume.get_cutout_request(
            self.chanResource, 'GET', 'application/blosc-python', url_prefix, token,
            resolution, x_rng_lst, y_rng_lst, z_rng_lst, t_rng_lst, data)
        self.assertEqual(
            '{}/{}/{}/{}/{}/{}/{}/{}/{}/{}/{}/'.format(url_prefix, self.test_volume.version,
                                                       self.test_volume.endpoint, self.chanResource.coll_name,
                                                       self.chanResource.exp_name, self.chanResource.name, resolution,
                                                       x_range, y_range, z_range, time_range),
            actual.url)
        self.assertEqual('Token {}'.format(token), actual.headers['Authorization'])
        self.assertEqual('application/blosc-python', actual.headers['Content-Type'])

    def test_get_cutout_request_with_ids(self):
        """Test request generated for a filtered cutout."""
        url_prefix = 'https://api.theboss.io'
        token = 'foobar'
        resolution = 0
        x_rng_lst = [20, 40]
        x_range = '20:40'
        y_rng_lst = [50, 70]
        y_range = '50:70'
        z_rng_lst = [30, 50]
        z_range = '30:50'
        t_rng_lst = [10, 25]
        time_range = '10:25'
        id_list = [10, 5]
        id_list_str = '10,5'
        data = numpy.random.randint(0, 3000, (15, 20, 20, 20), numpy.uint16)

        actual = self.test_volume.get_cutout_request(
            self.chanResource, 'GET', 'application/blosc-python', url_prefix, token,
            resolution, x_rng_lst, y_rng_lst, z_rng_lst, t_rng_lst, id_list=id_list)
        self.assertEqual(
            '{}/{}/{}/{}/{}/{}/{}/{}/{}/{}/{}/?filter={}'.format(url_prefix, self.test_volume.version,
            self.test_volume.endpoint, self.chanResource.coll_name,
            self.chanResource.exp_name, self.chanResource.name, resolution,
            x_range, y_range, z_range, time_range, id_list_str),
            actual.url)
        self.assertEqual('Token {}'.format(token), actual.headers['Authorization'])
        self.assertEqual('application/blosc-python', actual.headers['Content-Type'])

    def test_get_cutout_request_with_ids_and_access_mode(self):
        """Test request generated for a filtered cutout."""
        url_prefix = 'https://api.theboss.io'
        token = 'foobar'
        resolution = 0
        x_rng_lst = [20, 40]
        x_range = '20:40'
        y_rng_lst = [50, 70]
        y_range = '50:70'
        z_rng_lst = [30, 50]
        z_range = '30:50'
        t_rng_lst = [10, 25]
        time_range = '10:25'
        id_list = [10, 5]
        id_list_str = '10,5'
        data = numpy.random.randint(0, 3000, (15, 20, 20, 20), numpy.uint16)

        actual = self.test_volume.get_cutout_request(
            self.chanResource, 'GET', 'application/blosc-python', url_prefix, token,
            resolution, x_rng_lst, y_rng_lst, z_rng_lst, t_rng_lst, id_list=id_list, access_mode=CacheMode.no_cache)
        self.assertEqual(
            '{}/{}/{}/{}/{}/{}/{}/{}/{}/{}/{}/?filter={}&access-mode=no-cache'.format(url_prefix, self.test_volume.version,
            self.test_volume.endpoint, self.chanResource.coll_name,
            self.chanResource.exp_name, self.chanResource.name, resolution,
            x_range, y_range, z_range, time_range, id_list_str),
            actual.url)
        self.assertEqual('Token {}'.format(token), actual.headers['Authorization'])
        self.assertEqual('application/blosc-python', actual.headers['Content-Type'])

    def test_get_reserve_request(self):
        url_prefix = 'https://api.theboss.io'
        token = 'foobar'
        num_ids = 20

        actual = self.test_volume.get_reserve_request(
            self.annoResource, 'GET', 'application/json', url_prefix, token,
            num_ids)

        expected = '{}/{}/reserve/{}/{}/{}/{}'.format(
            url_prefix, self.test_volume.version, self.annoResource.coll_name,
            self.annoResource.exp_name, self.annoResource.name, num_ids)

        self.assertEqual(expected, actual.url)

    def test_get_bounding_box_request_loose(self):
        url_prefix = 'https://api.theboss.io'
        token = 'foobar'
        resolution = 0
        bb_type = 'loose'
        id = 55555

        actual = self.test_volume.get_bounding_box_request(
            self.annoResource, 'GET', 'application/json', url_prefix, token,
            resolution, id, bb_type)

        expected = '{}/{}/boundingbox/{}/{}/{}/{}/{}/?type={}'.format(
            url_prefix, self.test_volume.version, self.annoResource.coll_name,
            self.annoResource.exp_name, self.annoResource.name, resolution,
            id, bb_type)

        self.assertEqual(expected, actual.url)

    def test_build_ids_url(self):
        url_prefix = 'https://api.theboss.io'
        resolution = 0
        x_range = [0, 100]
        x_range_str = '0:100'
        y_range = [10, 50]
        y_range_str = '10:50'
        z_range = [20, 42]
        z_range_str = '20:42'
        t_range = [0, 1]
        t_range_str = '0:1'

        actual = self.test_volume.build_ids_url(
            self.annoResource, url_prefix, resolution,
            x_range, y_range, z_range, t_range)

        expected = '{}/{}/ids/{}/{}/{}/{}/{}/{}/{}/{}/'.format(
            url_prefix, self.test_volume.version, self.annoResource.coll_name,
            self.annoResource.exp_name, self.annoResource.name,
            resolution, x_range_str, y_range_str, z_range_str, t_range_str)

        self.assertEqual(expected, actual)

    def test_get_ids_request(self):
        url_prefix = 'https://api.theboss.io'
        token = 'foobar'
        resolution = 0
        x_range = [0, 100]
        x_range_str = '0:100'
        y_range = [10, 50]
        y_range_str = '10:50'
        z_range = [20, 42]
        z_range_str = '20:42'
        t_range = [0, 1]
        t_range_str = '0:1'

        actual = self.test_volume.get_ids_request(
            self.annoResource, 'GET', 'application/json', url_prefix, token,
            resolution, x_range, y_range, z_range, t_range)

        expected = '{}/{}/ids/{}/{}/{}/{}/{}/{}/{}/{}/'.format(
            url_prefix, self.test_volume.version, self.annoResource.coll_name,
            self.annoResource.exp_name, self.annoResource.name,
            resolution, x_range_str, y_range_str, z_range_str, t_range_str)

        self.assertEqual(expected, actual.url)

    def test_convert_int_list_to_comma_sep_str_1_ele(self):
        """Test with a list with one element."""
        expected = '2'
        actual = self.test_volume.convert_int_list_to_comma_sep_str([2])
        self.assertEqual(expected, actual)

    def test_convert_int_list_to_comma_sep_str_multi_ele(self):
        """Test with a list with multiple elements."""
        expected = '2,6,9'
        actual = self.test_volume.convert_int_list_to_comma_sep_str([2, 6, 9])
        self.assertEqual(expected, actual)
Пример #8
0
 def test_setting_datatype_means_cutout_ready(self):
     chan = ChannelResource('somechan', 'foo', 'bar')
     chan.datatype = 'uint16'
     self.assertTrue(chan.cutout_ready)
Пример #9
0
 def test_setting_datatype_means_cutout_ready_at_construction(self):
     chan = ChannelResource('somechan', 'foo', 'bar', datatype='uint8')
     self.assertTrue(chan.cutout_ready)
Пример #10
0
 def test_channel_defaults_to_uint8(self):
     chan = ChannelResource('somechan', 'foo', 'bar')
     self.assertEqual('uint8', chan.datatype)
Пример #11
0
 def test_init_status_false(self):
     chan = ChannelResource('somechan', 'foo', 'bar')
     self.assertFalse(chan.cutout_ready)
Пример #12
0
 def setUp(self):
     self.chan = ChannelResource('mychan', 'foo', 'bar', 'image')
Пример #13
0
class TestChannelResource(unittest.TestCase):
    def setUp(self):
        self.chan = ChannelResource('mychan', 'foo', 'bar', 'image')

    def test_init_status_false(self):
        chan = ChannelResource('somechan', 'foo', 'bar')
        self.assertFalse(chan.cutout_ready)

    def test_channel_defaults_to_uint8(self):
        chan = ChannelResource('somechan', 'foo', 'bar')
        self.assertEqual('uint8', chan.datatype)

    def test_setting_datatype_means_cutout_ready_at_construction(self):
        chan = ChannelResource('somechan', 'foo', 'bar', datatype='uint8')
        self.assertTrue(chan.cutout_ready)

    def test_setting_datatype_means_cutout_ready(self):
        chan = ChannelResource('somechan', 'foo', 'bar')
        chan.datatype = 'uint16'
        self.assertTrue(chan.cutout_ready)

    def test_default_source_is_empty(self):
        self.assertEqual([], self.chan.sources)

    def test_default_related_is_empty(self):
        self.assertEqual([], self.chan.related)

    def test_source_string_stored_as_list(self):
        self.chan.sources = 'foo'
        self.assertEqual(['foo'], self.chan.sources)

    def test_related_string_stored_as_list(self):
        self.chan.related = 'foo'
        self.assertEqual(['foo'], self.chan.related)

    def test_source_list(self):
        self.chan.source = ['foo', 'bar']
        self.assertEqual(['foo', 'bar'], self.chan.source)

    def test_related_list(self):
        self.chan.related = ['foo', 'bar']
        self.assertEqual(['foo', 'bar'], self.chan.related)

    def test_valid_volume(self):
        self.assertTrue(self.chan.valid_volume())

    def test_get_route(self):
        self.assertEqual(
            '{}/experiment/{}/channel/{}'.format(self.chan.coll_name,
                                                 self.chan.exp_name,
                                                 self.chan.name),
            self.chan.get_route())

    def test_get_list_route(self):
        self.assertEqual(
            '{}/experiment/{}/channel/'.format(self.chan.coll_name,
                                               self.chan.exp_name),
            self.chan.get_list_route())

    def test_validate_datatype_uint8(self):
        exp = 'uint8'
        self.assertEqual(exp, self.chan.validate_datatype(exp))

    def test_validate_datatype_uint16(self):
        exp = 'uint16'
        self.assertEqual(exp, self.chan.validate_datatype(exp))

    def test_validate_datatype_uint64(self):
        exp = 'uint64'
        self.assertEqual(exp, self.chan.validate_datatype(exp))

    def test_validate_datatype_bad(self):
        with self.assertRaises(ValueError):
            self.chan.validate_datatype('bigint')
Пример #14
0
    def __init__(
        self,
        channel: Union[ChannelResource, Tuple, str],
        resolution: int = 0,
        volume_provider: VolumeProvider = None,
        axis_order: str = AxisOrder.ZYX,
        create_new: bool = False,
        description: Optional[str] = None,
        dtype: Optional[str] = None,
        extents: Optional[Tuple[int, int, int]] = None,
        voxel_size: Optional[Tuple[int, int, int]] = None,
        voxel_unit: Optional[str] = None,
        downsample_levels: int = 6,
        downsample_method: Optional[str] = "anisotropic",
        coordinate_frame_name: Optional[str] = None,
        coordinate_frame_desc: Optional[str] = None,
        collection_desc: Optional[str] = None,
        experiment_desc: Optional[str] = None,
        source_channel: Optional[str] = None,
        boss_config: Optional[dict] = None,
    ) -> None:
        """
        Construct a new intern-backed array.

        Arguments:
            channel (intern.resource.boss.ChannelResource): The channel from
                which data will be downloaded.
            resolution (int: 0): The native resolution or MIP to use
            volume_provider (VolumeProvider): The remote-like to use
            axis_order (str = AxisOrder.ZYX): The axis-ordering to use for data
                cutouts. Defaults to ZYX. DOES NOT affect the `voxel_size` or
                `extents` arguments to this constructor.
            create_new (bool: False): Whether to create new Resources if they
                do not exist. Does not work with public token.
            dtype (str): Only required if `create_new = True`. Specifies the
                numpy-style datatype for this new dataset (e.g. "uint8").
            description (str): Only required if `create_new = True`. Sets the
                description for the newly-created collection, experiment,
                channel, and coordframe resources.
            extents: Optional[Tuple[int, int, int]]: Only required if
                `create_new = True`. Specifies the total dataset extents of
                this new dataset, in ZYX order.
            voxel_size: Optional[Tuple[int, int, int]]: Only required if
                `create_new = True`. Specifies the voxel dimensions of this new
                dataset, in ZYX order.
            voxel_unit: Optional[str]: Only required if `create_new = True`.
                Specifies the voxel-dimension unit. For example, "nanometers".
            downsample_levels (int: 6): The number of downsample levels.
            downsample_method (Optional[str]): The type of downsample to use.
                If unset, defaults to 'anisotropic'.
            coordinate_frame_name (Optional[str]): If set, the name to use for
                the newly created coordinate frame. If not set, the name of the
                coordinate frame will be chosen automatically.
            coordinate_frame_desc (Optional[str]): If set, the description text
                to use for the newly created coordinate frame. If not set, the
                description will be chosen automatically.
            collection_desc (Optional[str]): The description text to use for a
                newly created collection. If not set, the description will be
                chosen automatically.
            experiment_desc (Optional[str]): The description text to use for a
                newly created experiment. If not set, the description will be
                chosen automatically.
            source_channel (Optional[str]): The channel to use as the source
                for this new channel, if `create_new` is True and this is
                going to be an annotation channel (dtype!=uint8).
            boss_config (Optional[dict]): The BossRemote configuration dict to
                use in order to authenticate with a BossDB remote. This option
                is mutually exclusive with the VolumeProvider configuration. If
                the `volume_provider` arg is set, this will be ignored.

        """
        self.axis_order = axis_order

        # Handle inferring the remote from the channel:
        volume_provider = volume_provider or _infer_volume_provider(channel)
        if volume_provider is None:
            if boss_config:
                volume_provider = _BossDBVolumeProvider(
                    BossRemote(boss_config))
            else:
                volume_provider = _BossDBVolumeProvider()

        # Handle custom Remote:
        self.volume_provider = volume_provider

        if create_new:

            if self.volume_provider.get_vp_type() != "bossdb":
                raise ValueError(
                    "Creating new resources with a non-bossdb volume provider is not currently supported."
                )

            # We'll need at least `extents` and `voxel_size`.
            description = description or "Created with intern"
            dtype = dtype or "uint8"

            if extents is None:
                raise ValueError(
                    "If `create_new` is True, you must specify the extents of the new coordinate frame as a [x, y, z]."
                )
            if voxel_size is None:
                raise ValueError(
                    "If `create_new` is True, you must specify the voxel_size of the new coordinate frame as a [x, y, z]."
                )

            uri = _parse_bossdb_uri(channel)

            # create collection if it doesn't exist:
            try:
                # Try to get an existing collection:
                collection = self.volume_provider.get_project(
                    CollectionResource(uri.collection))
            except:
                # Create the collection:
                collection = CollectionResource(uri.collection,
                                                description=collection_desc
                                                or description)
                self.volume_provider.create_project(collection)

            # create coordframe if it doesn't exist:
            try:
                # Try to get an existing coordframe:
                coordframe = self.volume_provider.get_project(
                    CoordinateFrameResource(
                        coordinate_frame_name
                        or f"CF_{uri.collection}_{uri.experiment}"))
            except:
                # Default to nanometers if a voxel unit isn't provided
                voxel_unit = voxel_unit or "nanometers"
                # Create the coordframe:
                coordframe = CoordinateFrameResource(
                    coordinate_frame_name
                    or f"CF_{uri.collection}_{uri.experiment}",
                    description=coordinate_frame_desc or description,
                    x_start=0,
                    y_start=0,
                    z_start=0,
                    x_stop=extents[2],
                    y_stop=extents[1],
                    z_stop=extents[0],
                    x_voxel_size=voxel_size[2],
                    y_voxel_size=voxel_size[1],
                    z_voxel_size=voxel_size[0],
                    voxel_unit=voxel_unit,
                )
                self.volume_provider.create_project(coordframe)

            # create experiment if it doesn't exist:
            try:
                # Try to get an existing experiment:
                experiment = self.volume_provider.get_project(
                    ExperimentResource(uri.experiment, uri.collection))
            except:
                # Create the experiment:
                experiment = ExperimentResource(
                    uri.experiment,
                    uri.collection,
                    description=experiment_desc or description,
                    coord_frame=coordframe.name,
                    num_hierarchy_levels=downsample_levels,
                    hierarchy_method=downsample_method,
                )
                self.volume_provider.create_project(experiment)

            # create channel if it doesn't exist:
            try:
                # Try to get an existing channel:
                channel = self.volume_provider.get_project(
                    ChannelResource(uri.channel, uri.collection,
                                    uri.experiment))
            except:
                # Create the channel:
                channel = ChannelResource(
                    uri.channel,
                    uri.collection,
                    uri.experiment,
                    description=description,
                    type="image"
                    if dtype in ["uint8", "uint16"] else "annotation",
                    datatype=dtype,
                    sources=[source_channel] if source_channel else [],
                )
                self.volume_provider.create_project(channel)

        self.resolution = resolution
        # If the channel is set as a Resource, then use that resource.
        if isinstance(channel, ChannelResource):
            self._channel = channel
        # If it is set as a string, then parse the channel and generate an
        # intern.Resource from a bossDB URI.
        else:  # if isinstance(channel, str):
            uri = {
                "BossDB": _parse_bossdb_uri,
                "CloudVolumeOpenData": _parse_cloudvolume_uri,
            }[self.volume_provider.get_vp_type()](channel)
            self.resolution = (uri.resolution if not (uri.resolution is None)
                               else self.resolution)
            self._channel = self.volume_provider.get_channel(
                uri.channel, uri.collection, uri.experiment)

        # Set col/exp/chan based upon the channel or URI provided.
        self.collection_name = self._channel.coll_name
        self.experiment_name = self._channel.exp_name
        self.channel_name = self._channel.name

        # Create a pointer to the metadata for the channel.
        self._channel_metadata = Metadata(self._channel)