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)
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)
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)
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)
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
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
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)
def test_setting_datatype_means_cutout_ready(self): chan = ChannelResource('somechan', 'foo', 'bar') chan.datatype = 'uint16' self.assertTrue(chan.cutout_ready)
def test_setting_datatype_means_cutout_ready_at_construction(self): chan = ChannelResource('somechan', 'foo', 'bar', datatype='uint8') self.assertTrue(chan.cutout_ready)
def test_channel_defaults_to_uint8(self): chan = ChannelResource('somechan', 'foo', 'bar') self.assertEqual('uint8', chan.datatype)
def test_init_status_false(self): chan = ChannelResource('somechan', 'foo', 'bar') self.assertFalse(chan.cutout_ready)
def setUp(self): self.chan = ChannelResource('mychan', 'foo', 'bar', 'image')
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')
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)