Esempio n. 1
0
def preprocess_data(x, y):
    x = np.swapaxes(x, 0, 1)
    y = np.swapaxes(y, 0, 1)
    x = np.array(x)
    y = np.array(y)

    return x, y
Esempio n. 2
0
def deskew(data, angle, dx, dz, rotate=True, return_resolution=True, out=None):
    """
    Args:
        data (ndarray): 3-D array to apply deskew
        angle (float): angle between the objective and coverslip, in degree
        dx (float): X resolution
        dz (float): Z resolution
        rotate (bool, optional): rotate and crop the output
        return_resolution (bool, optional): return deskewed X/Z resolution
        out (ndarray, optional): array to store the result
    """
    angle = radians(angle)

    # shift along X axis, in pixels
    shift = dz * cos(angle) / dx
    logger.debug(f"layer shift: {shift:.04f} px")

    # estimate new size
    nw, nv, nu = data.shape
    nz, ny, nx = nw, nv, nu + ceil(shift * (nw - 1))

    # upload texture
    ch = ChannelFormatDescriptor(32, 0, 0, 0,
                                 runtime.cudaChannelFormatKindFloat)
    arr = CUDAarray(ch, nu, nw)
    res = ResourceDescriptor(runtime.cudaResourceTypeArray, cuArr=arr)

    address_mode = (runtime.cudaAddressModeBorder,
                    runtime.cudaAddressModeBorder)
    tex = TextureDescriptor(address_mode, runtime.cudaFilterModeLinear,
                            runtime.cudaReadModeElementType)

    # transpose
    data = np.swapaxes(data, 0, 1)
    data = np.ascontiguousarray(data)

    data_in = data.astype(np.float32)
    data_out = cp.empty((ny, nz, nx), np.float32)
    for i, layer in enumerate(data_in):
        arr.copy_from(layer)  # TODO use stream
        texobj = TextureObject(res, tex)

        kernels["shear_kernel"](
            (ceil(nx / 16), ceil(nz / 16)),
            (16, 16),
            (data_out[i, ...], texobj, nx, nz, nu, np.float32(shift)),
        )

    data_out = cp.swapaxes(data_out, 0, 1)
    data_out = cp.asnumpy(data_out)
    data_out = data_out.astype(data.dtype)

    if return_resolution:
        # new resolution
        dz *= sin(angle)
        return data_out, (dz, dx)
    else:
        return data_out
Esempio n. 3
0
def dot_adjoint_0(B, G, A_ndim, B_ndim):
    # The adjoint of the operator
    # A |--> np.dot(A, B)
    if B_ndim == 0 or B_ndim == 1 or A_ndim == 0:
        contract_num = max(0, B_ndim - (A_ndim != 0))
        return ocp.tensordot(G, B, contract_num)

    else:
        return ocp.tensordot(G, ocp.swapaxes(B, -1, -2), B_ndim - 1)
Esempio n. 4
0
 def next_batch(self,
                batch_size,
                reshuffle_after_pass=True,
                swapaxes=False):
     if self.n < batch_size:
         raise ValueError('Batch size can be at most the dataset size')
     actual_batch_size = min(batch_size, self.n - self.batch_start)
     if actual_batch_size < batch_size:
         if reshuffle_after_pass:
             self.cur_order = np.random.permutation(self.n)
         self.batch_start = 0
     batch_end = self.batch_start + batch_size
     batch_xs = self.xs[self.cur_order[self.batch_start:batch_end], ...]
     batch_ys = self.ys[self.cur_order[self.batch_start:batch_end], ...]
     self.batch_start += batch_size
     if swapaxes:
         batch_xs = np.swapaxes(batch_xs, 0, 1)
         batch_ys = np.swapaxes(batch_ys, 0, 1)
     return batch_xs, batch_ys
Esempio n. 5
0
def apply_unitary_transformation_to_density_matrices_cupy(
    unitary: cupy.ndarray, density_matrices: cupy.ndarray
):
    dim1, dim2 = unitary.shape
    num_states, dim3, dim4 = density_matrices.shape
    assert dim1 == dim2 == dim3 == dim4
    # unitary U[i,k] D[nwf,k,l] -> B[i,nwf,l]
    mat_b = tensordot(unitary, density_matrices, axes=[[1], [1]])
    # B[i,nwf,k] U'[k,l] -> ret[i,nwf,l]
    ret = tensordot(mat_b, transpose(conj(unitary)), axes=[[2], [0]])
    return swapaxes(ret, axis1=0, axis2=1)
Esempio n. 6
0
def apply_isometry_to_density_matrices_cupy(
    isometry: cupy.ndarray, density_matrices: cupy.ndarray
):
    outdim, dim1 = isometry.shape
    num_states, dim2, dim3 = density_matrices.shape
    assert dim1 == dim2 == dim3

    # unitary U[i,k] D[nwf,k,l] -> B[i,nwf,l]
    mat_b = tensordot(isometry, density_matrices, axes=[[1], [1]])
    # B[i,nwf,k] U'[k,l] -> ret[i,nwf,l]
    ret = tensordot(mat_b, transpose(conj(isometry)), axes=[[2], [0]])
    return swapaxes(ret, axis1=0, axis2=1)
Esempio n. 7
0
    def ycbcr2rgb(self, y=None, cb=None, cr=None):
        """colorspacetransformation from y,cb,cr to rgb
            input: y,cb,cr values saved as lists
            channels = true for rgb arrays, false for pil image
            return: rgb image as PIL.Image"""
        if(args.verbose):
            print("Performing colorspace transformation from YCbCr to RGB")

        ycbcr = np.array((y,cb,cr))
        if args.numba:
            rgb = numba_ycbcr2rgb(self.backtrafo_table, ycbcr)
        else:
            ycbcr[1] -= 128
            ycbcr[2] -= 128
            rgb = self.backtrafo_table @ ycbcr
            rgb = np.rint(rgb).astype(np.int16)

        rgb = rgb.reshape(3, self.height_e, self.width_e)
        rgb = np.clip(rgb, 0, 255)
        # bring axes in correct order
        rgb = np.swapaxes(rgb, 0,2)
        rgb = np.swapaxes(rgb, 0,1)
        if args.cupy:
            rgb_img = Image.fromarray(np.asnumpy(rgb).astype(np.uint8),'RGB')

        else:
            rgb_img = Image.fromarray(rgb.astype(np.uint8),'RGB')

        crop_recomb = self.cropping_back(rgb_img)

        r = np.array(crop_recomb.getchannel('R')).flatten().astype(np.int16)
        g = np.array(crop_recomb.getchannel('G')).flatten().astype(np.int16)
        b = np.array(crop_recomb.getchannel('B')).flatten().astype(np.int16)
        rgb_out = np.concatenate((np.array([r]), np.array([g]), np.array([b])))

        if(args.debug):
            crop_recomb.save(os.path.join(inputpath, args.output, "debug", infilename + "_rücktrafo.png"))

        return crop_recomb, rgb_out
Esempio n. 8
0
 def dot_product_normalized_trans(self, coef_vector, norms):
     product = np.zeros(self.num_cols)
     loc = 0
     for i in range(len(self.files)):
         with cp.cuda.Device(self.gpu_list[i % self.num_gpus]):
             norm_gpu = cp.asarray(norms)
             coef = cp.asarray(coef_vector)
             matrix_part = cp.load(self.files[i])
             matrix_part = matrix_part / norm_gpu
             matrix_part = cp.swapaxes(matrix_part, 0, 1)
             n = matrix_part.shape[1]
             prod = cp.matmul(matrix_part, coef[loc:loc + n])
             loc = loc + n
             product = product + prod.get()
     return product
Esempio n. 9
0
def find_prob(measured_qubits, sub_state, states):

    # Make sure measured qubit numbers are in ascending order
    qubits = measured_qubits
    qubits.sort()

    # Make a copy of given states in order not to alter them
    a = states.copy()
    d1, d2 = a.shape  # d1 = number of circuit runs, d2 = 2 ** N
    N = int(rint(log2(d2)))

    # Reshape to rank-(N+1) tensor
    a = a.reshape([d1] + [2] * N)

    # K = number of measured qubits, M = number of qubits not measured
    K = len(qubits)
    M = N - K

    # Reorder qubit number axes
    for i in range(K):
        a = swapaxes(a, i + 1, qubits[i] + 1)

    # Flatten arrays for 2 groups of qubits
    a = a.reshape([d1] + [2**K] + [2**M])

    # Broadcast multiply coefficients
    a = swapaxes(a, 0, 1)
    a = multiply(a.T, sub_state).T

    # Sum over coefficients
    a = a.sum(axis=0)
    a = abs(a)**2
    a = a.sum(axis=1)

    # Return probability of measuring a substate for all circuit runs
    return a
Esempio n. 10
0
def dot_adjoint_1(A, G, A_ndim, B_ndim):
    # The adjoint of the operator
    # B |--> np.dot(A, B)
    needs_transpose = B_ndim > 1 and A_ndim != 0
    swap = ((lambda x: ocp.swapaxes(x, -1, -2)) if needs_transpose else
            (lambda x: x))  # noqa: E501
    if A_ndim == 0 or A_ndim == 1 or B_ndim == 0:
        contract_num = max(0, A_ndim - (B_ndim != 0))
        return swap(ocp.tensordot(G, A, contract_num))

    else:
        return swap(
            ocp.tensordot(
                G,
                A,
                [
                    range(-A_ndim - B_ndim + 2, -B_ndim + 1),
                    range(A_ndim - 1),
                ],  # noqa: E501
            ))
Esempio n. 11
0
    def test_rgb2luv_brucelindbloom(self):
        """
        Test the RGB->Lab conversion by comparing to the calculator on the
        authoritative Bruce Lindbloom
        [website](http://brucelindbloom.com/index.html?ColorCalculator.html).
        """
        # Obtained with D65 white point, sRGB model and gamma
        # ftm: off
        gt_for_colbars = cp.asarray([
            [100, 0, 0],
            [97.1393, 7.7056, 106.7866],
            [91.1132, -70.4773, -15.2042],
            [87.7347, -83.0776, 107.3985],
            [60.3242, 84.0714, -108.6834],
            [53.2408, 175.0151, 37.7564],
            [32.2970, -9.4054, -130.3423],
            [0, 0, 0]]).T

        # ftm: on
        gt_array = cp.swapaxes(gt_for_colbars.reshape(3, 4, 2), 0, 2)
        assert_array_almost_equal(rgb2luv(self.colbars_array),
                                  gt_array, decimal=2)
Esempio n. 12
0
    def test_rgb2lab_brucelindbloom(self):
        """
        Test the RGB->Lab conversion by comparing to the calculator on the
        authoritative Bruce Lindbloom
        [website](http://brucelindbloom.com/index.html?ColorCalculator.html).
        """
        # Obtained with D65 white point, sRGB model and gamma
        # ftm: off
        gt_for_colbars = cp.asarray([
            [100, 0, 0],
            [97.1393, -21.5537, 94.4780],
            [91.1132, -48.0875, -14.1312],
            [87.7347, -86.1827, 83.1793],
            [60.3242, 98.2343, -60.8249],
            [53.2408, 80.0925, 67.2032],
            [32.2970, 79.1875, -107.8602],
            [0, 0, 0]]).T

        # ftm: on
        gt_array = cp.swapaxes(gt_for_colbars.reshape(3, 4, 2), 0, 2)
        assert_array_almost_equal(rgb2lab(self.colbars_array), gt_array,
                                  decimal=2)
Esempio n. 13
0
    def transform(self, images):
        """
        Parameters
        ----------
        images: np.ndarray
            | Color / grayscale images of shape
            | (n_images, height, width, n_channels) or
            | (n_images, height, width)

        Returns
        -------
        X: np.ndarray
            A set of feature vectors of shape (n_images, n_features)
            where :code:`n_features` is determined by the hyperparameters
        """
        images = self.process_input(images)
        # images.shape == (n_images, n_channels, y, x)

        N = images.shape[0]
        filters_l1 = components_to_filters(
            self.pca_l1.components_,
            n_channels=images.shape[1],
            filter_shape=self.filter_shape_l1,
        )

        filters_l2 = components_to_filters(self.pca_l2.components_,
                                           n_channels=1,
                                           filter_shape=self.filter_shape_l2)

        filters_l3 = components_to_filters(self.pca_l3.components_,
                                           n_channels=1,
                                           filter_shape=self.filter_shape_l3)

        if gpu_enabled():
            images = to_gpu(images)
            filters_l1 = to_gpu(filters_l1)
            filters_l2 = to_gpu(filters_l2)
            filters_l3 = to_gpu(filters_l3)

        images = convolution_2d(images.astype('float32'),
                                filters_l1,
                                stride=self.step_shape_l1).data

        print("Memory: {}Mb".format(memory_profiler.memory_usage()))

        images = images.reshape(-1, *images.shape[2:4])
        images = convolution_2d(
            images.reshape(
                images.shape[0], 1, images.shape[1],
                images.shape[2]).astype('float32'),  # 1 channel images
            filters_l2,
            stride=self.step_shape_l2).data

        print("Memory: {}Mb".format(memory_profiler.memory_usage()))

        images = images.reshape(N, self.n_l1_output * self.n_l2_output,
                                images.shape[2], images.shape[3])
        images = xp.swapaxes(images, 0, 1)

        print(images.shape)
        # L1*L2.shape == (L1*L2, n_images, y, x)
        # iterate over each L1*L2 output

        X = []
        for maps in images:
            n_images, h, w = maps.shape
            #print(type(maps))
            #print(type(filters_l3))
            maps = convolution_2d(
                maps.reshape(n_images, 1, h,
                             w).astype('float32'),  # 1 channel images
                filters_l3,
                stride=self.step_shape_l3).data

            # maps.shape == (n_images, L1*L2*L3, y, x) right here
            maps = binarize(maps)
            maps = binary_to_decimal(maps)
            # maps.shape == (n_images, y, x)

            t1 = timeit.default_timer()
            x = self.histogram(maps)
            t2 = timeit.default_timer()
            hist_time = t2 - t1
            print("hist_time: %f" % hist_time)
            # x is a set of feature vectors.
            # The shape of x is (n_images, vector length)
            X.append(x)

        # concatenate over L1
        X = xp.hstack(X)

        if gpu_enabled():
            X = to_cpu(X)

        X = X.astype(np.float32)
        print("Memory: {}Mb".format(memory_profiler.memory_usage()))
        # The shape of X is (n_images, L1 * vector length)
        return X
Esempio n. 14
0
def evaluate_chunks(
        results: [cp.ndarray, cp.ndarray,
                  cp.ndarray],  # closest triangle, distance, projection
        all_pts: cp.ndarray = None,
        vertices: cp.ndarray = None,
        edges: cp.ndarray = None,
        edge_norms: cp.ndarray = None,
        edge_normssq: cp.ndarray = None,
        normals: cp.ndarray = None,
        norms: cp.ndarray = None,
        normssq: cp.ndarray = None,
        zero_tensor: cp.ndarray = None,
        one_tensor: cp.ndarray = None,
        tris: cp.ndarray = None,
        vertex_normals: cp.ndarray = None,
        bounding_box: dict = None,
        chunk_size: int = None,
        num_verts: int = None) -> None:

    #
    # Expand vertex normals if non empty
    if vertex_normals is not None:
        vertex_normals = vertex_normals[tris]
        vertex_normals = cp.tile(cp.expand_dims(vertex_normals, axis=2),
                                 (1, 1, chunk_size, 1))

    # begin = time.time()
    #
    # Load and extend the batch
    num_chunks = all_pts.shape[0] // chunk_size
    for i in range(num_chunks):
        #
        # Get subset of the query points
        start_index = i * chunk_size
        end_index = (i + 1) * chunk_size
        pts = all_pts[start_index:end_index, :]

        #
        # Match the dimensions to those assumed above.
        #    REPEATED       REPEATED
        # [triangle_index, vert_index, querypoint_index, coordinates]
        pts = cp.tile(cp.expand_dims(pts, axis=(0, 1)), (num_verts, 3, 1, 1))

        #
        # Compute the differences between
        # vertices on each triangle and the
        # points of interest
        #
        # [triangle_index, vert_index, querypoint_index, coordinates]
        # ===================
        # [:,0,:,:] = p - p1
        # [:,1,:,:] = p - p2
        # [:,2,:,:] = p - p3
        diff_vectors = pts - vertices

        #
        # Compute alpha, beta, gamma
        barycentric = cp.empty(diff_vectors.shape)

        #
        # gamma = u x (p - p1)
        barycentric[:, 2, :, :] = cp.cross(edges[:, 0, :, :],
                                           diff_vectors[:, 0, :, :])
        # beta = (p - p1) x v
        barycentric[:, 1, :, :] = cp.cross(diff_vectors[:, 0, :, :],
                                           edges[:, 1, :, :])
        # alpha = w x (p - p2)
        barycentric[:, 0, :, :] = cp.cross(edges[:, 2, :, :],
                                           diff_vectors[:, 1, :, :])
        barycentric = cp.divide(
            cp.sum(cp.multiply(barycentric, normals), axis=3), normssq)

        #
        # Test conditions
        less_than_one = cp.less_equal(barycentric, one_tensor)
        more_than_zero = cp.greater_equal(barycentric, zero_tensor)

        #
        #     if 0 <= gamma and gamma <= 1
        #    and 0 <= beta and beta <= 1
        #    and 0 <= alpha and alpha <= 1:
        cond1 = cp.logical_and(less_than_one, more_than_zero)

        #
        #     if gamma <= 0:
        cond2 = cp.logical_not(more_than_zero[:, 2, :])
        cond2 = cp.tile(cp.expand_dims(cond2, axis=1), (1, 3, 1))

        #
        #     if beta <= 0:
        cond3 = cp.logical_not(more_than_zero[:, 1, :])
        cond3 = cp.tile(cp.expand_dims(cond3, axis=1), (1, 3, 1))

        #
        #     if alpha <= 0:
        cond4 = cp.logical_not(more_than_zero[:, 0, :])
        cond4 = cp.tile(cp.expand_dims(cond4, axis=1), (1, 3, 1))

        #
        # Get the projections for each case
        xi = cp.empty(barycentric.shape)
        barycentric_ext = cp.tile(cp.expand_dims(barycentric, axis=3),
                                  (1, 1, 1, 3))
        proj = cp.sum(cp.multiply(barycentric_ext, vertices), axis=1)
        #
        #     if 0 <= gamma and gamma <= 1
        #    and 0 <= beta and beta <= 1
        #    and 0 <= alpha and alpha <= 1:
        xi[cond1] = barycentric[cond1]

        #
        # if gamma <= 0:
        #  x = p - p1
        #  u = p2 - p1
        #  a = p1
        #  b = p2
        t2 = cp.divide(
            #
            # u.dot(x)
            cp.sum(cp.multiply(edges[:, 0, :, :], diff_vectors[:, 0, :, :]),
                   axis=2),
            edge_normssq[:, 0])
        xi2 = cp.zeros((t2.shape[0], 3, t2.shape[1]))
        xi2[:, 0, :] = -t2 + 1
        xi2[:, 1, :] = t2
        #
        t2 = cp.tile(cp.expand_dims(t2, axis=2), (1, 1, 3))
        lz = cp.less(t2, cp.zeros(t2.shape))
        go = cp.greater(t2, cp.ones(t2.shape))
        proj2 = vertices[:, 0, :, :] + cp.multiply(t2, edges[:, 0, :, :])
        proj2[lz] = vertices[:, 0, :, :][lz]
        proj2[go] = vertices[:, 1, :, :][go]
        #
        xi[cond2] = xi2[cond2]
        proj[cp.swapaxes(cond2, 1, 2)] = proj2[cp.swapaxes(cond2, 1, 2)]

        #
        # if beta <= 0:
        #  x = p - p1
        #  v = p3 - p1
        #  a = p1
        #  b = p3
        t3 = cp.divide(
            #
            # v.dot(x)
            cp.sum(cp.multiply(edges[:, 1, :, :], diff_vectors[:, 0, :, :]),
                   axis=2),
            edge_normssq[:, 1])
        xi3 = cp.zeros((t3.shape[0], 3, t3.shape[1]))
        xi3[:, 0, :] = -t3 + 1
        xi3[:, 2, :] = t3
        #
        t3 = cp.tile(cp.expand_dims(t3, axis=2), (1, 1, 3))
        lz = cp.less(t3, cp.zeros(t3.shape))
        go = cp.greater(t3, cp.ones(t3.shape))
        proj3 = vertices[:, 0, :, :] + cp.multiply(t3, edges[:, 1, :, :])
        proj3[lz] = vertices[:, 0, :, :][lz]
        proj3[go] = vertices[:, 2, :, :][go]
        #
        xi[cond3] = xi3[cond3]
        proj[cp.swapaxes(cond3, 1, 2)] = proj3[cp.swapaxes(cond3, 1, 2)]

        #
        #     if alpha <= 0:
        #  y = p - p2
        #  w = p3 - p2
        #  a = p2
        #  b = p3
        t4 = cp.divide(
            #
            # w.dot(y)
            cp.sum(cp.multiply(edges[:, 2, :, :], diff_vectors[:, 1, :, :]),
                   axis=2),
            edge_normssq[:, 2])
        xi4 = cp.zeros((t4.shape[0], 3, t4.shape[1]))
        xi4[:, 1, :] = -t4 + 1
        xi4[:, 2, :] = t4
        #
        t4 = cp.tile(cp.expand_dims(t4, axis=2), (1, 1, 3))
        lz = cp.less(t4, cp.zeros(t4.shape))
        go = cp.greater(t4, cp.ones(t4.shape))
        proj4 = vertices[:, 1, :, :] + cp.multiply(t4, edges[:, 2, :, :])
        proj4[lz] = vertices[:, 1, :, :][lz]
        proj4[go] = vertices[:, 2, :, :][go]
        #
        xi[cond4] = xi4[cond4]
        proj[cp.swapaxes(cond4, 1, 2)] = proj4[cp.swapaxes(cond4, 1, 2)]

        vec_to_point = pts[:, 0, :, :] - proj
        distances = cp.linalg.norm(vec_to_point, axis=2)

        # n = "\n"
        # print(f"{pts[:,0,:,:]=}")
        # print(f"{proj=}")
        # print(f"{pts[:,0,:,:] - proj=}")
        # print(f"{distances=}")

        min_distances = cp.min(distances, axis=0)

        closest_triangles = cp.argmin(distances, axis=0)

        projections = proj[closest_triangles, np.arange(chunk_size), :]

        #
        # Distinguish close triangles
        is_close = cp.isclose(distances, min_distances)

        #
        # Determine sign
        signed_normal = normals[:, 0, :, :]
        if vertex_normals is not None:
            signed_normal = cp.sum(vertex_normals.transpose() * xi.transpose(),
                                   axis=2).transpose()

        is_negative = cp.less_equal(
            cp.sum(cp.multiply(vec_to_point, signed_normal), axis=2), 0.)

        #
        # Combine
        is_close_and_negative = cp.logical_and(is_close, is_negative)

        #
        # Determine if inside
        is_inside = cp.all(cp.logical_or(is_close_and_negative,
                                         cp.logical_not(is_close)),
                           axis=0)

        #
        # Overwrite the signs of points
        # that are outside of the box
        if bounding_box is not None:
            #
            # Extract
            rotation_matrix = cp.asarray(bounding_box['rotation_matrix'])
            translation_vector = cp.asarray(bounding_box['translation_vector'])
            size = cp.asarray(bounding_box['size'])
            #
            # Transform
            transformed_pts = cp.dot(
                all_pts[start_index:end_index, :] - translation_vector,
                rotation_matrix)

            #
            # Determine if outside bbox
            inside_bbox = cp.all(cp.logical_and(
                cp.less_equal(0., transformed_pts),
                cp.less_equal(transformed_pts, size)),
                                 axis=1)

            #
            # Treat points outside bbox as
            # being outside of lumen
            print(f"{inside_bbox=}")
            is_inside = cp.logical_and(is_inside, inside_bbox)

        #
        # Apply sign to indicate whether the distance is
        # inside or outside the mesh.
        min_distances[is_inside] = -1 * min_distances[is_inside]

        #
        # Emplace results
        # [triangle_index, vert_index, querypoint_index, coordinates]
        results[0][start_index:end_index] = closest_triangles
        results[1][start_index:end_index] = min_distances
        results[2][start_index:end_index, :] = projections
Esempio n. 15
0
 def test_swapaxes_failure(self):
     a = testing.shaped_arange((2, 3, 4))
     with self.assertRaises(ValueError):
         cupy.swapaxes(a, 3, 0)
Esempio n. 16
0
def eig_special_3d(S, full=False):
    """Eigensolution for symmetric real 3-by-3 matrices.

    Arguments:
        S: array-like
            A floating point array with shape ``(6, ...)`` containing structure tensor.
            Use float64 to avoid numerical errors. When using lower precision, ensure
            that the values of S are not very small/large. Pass cupy.ndarray to avoid copying S.
        full: bool, optional
            A flag indicating that all three eigenvalues should be returned.

    Returns:
        val: cupy.ndarray
            An array with shape ``(3, ...)`` containing sorted eigenvalues
        vec: cupy.ndarray
            An array with shape ``(3, ...)`` containing eigenvector corresponding to
            the smallest eigenvalue. If full, vec has shape ``(3, 3, ...)`` and contains
            all three eigenvectors.

    More:
        An analytic solution of eigenvalue problem for real symmetric matrix,
        using an affine transformation and a trigonometric solution of third
        order polynomial. See https://en.wikipedia.org/wiki/Eigenvalue_algorithm
        which refers to Smith's algorithm https://dl.acm.org/citation.cfm?id=366316.

    Authors: [email protected], 2019; [email protected], 2019-2020
    """
    S = np.asarray(S)

    # Check data type. Must be floating point.
    if not np.issubdtype(S.dtype, np.floating):
        raise ValueError('S must be floating point type.')

    # Flatten S.
    input_shape = S.shape
    S = S.reshape(6, -1)

    # Create v vector.
    v = np.array([[2 * np.pi / 3], [4 * np.pi / 3]], dtype=S.dtype)

    # Computing eigenvalues.

    # Allocate vec and val. We will use them for intermediate computations as well.
    if full:
        val = np.empty((3, ) + S.shape[1:], dtype=S.dtype)
        vec = np.empty((9, ) + S.shape[1:], dtype=S.dtype)
        tmp = np.empty((4, ) + S.shape[1:], dtype=S.dtype)
        B03 = val
        B36 = vec[:3]
    else:
        val = np.empty((3, ) + S.shape[1:], dtype=S.dtype)
        vec = np.empty((3, ) + S.shape[1:], dtype=S.dtype)
        tmp = np.empty((4, ) + S.shape[1:], dtype=S.dtype)
        B03 = val
        B36 = vec

    # Views for B.
    B0 = B03[0]
    B1 = B03[1]
    B2 = B03[2]
    B3 = B36[0]
    B4 = B36[1]
    B5 = B36[2]

    # Compute q, mean of diagonal. We need to use q multiple times later.
    # Using np.mean has precision issues.
    q = np.add(S[0], S[1], out=tmp[0])
    q += S[2]
    q /= 3

    # Compute S minus q. Insert it directly into B where it'll stay.
    Sq = np.subtract(S[:3], q, out=B03)

    # Compute s, off-diagonal elements. Store in part of B not yet used.
    s = np.sum(np.multiply(S[3:], S[3:], out=B36), axis=0, out=tmp[1])
    s *= 2

    # Compute p.
    p = np.sum(np.multiply(Sq, Sq, out=B36), axis=0, out=tmp[2])
    del Sq  # Last use of Sq.
    p += s

    p *= 1 / 6
    np.sqrt(p, out=p)

    # Compute inverse p, while avoiding 0 division.
    # Reuse s allocation and delete s to ensure we don't efter it's been reused.
    p_inv = s
    del s
    non_zero_p_mask = p == 0
    np.divide(1, p, out=p_inv)
    p_inv[non_zero_p_mask] = 0

    # Compute B. First part is already filled.
    B03 *= p_inv
    np.multiply(S[3:], p_inv, out=B36)

    # Compute d, determinant of B.
    d = np.prod(B03, axis=0, out=tmp[3])

    # Reuse allocation for p_inv and delete variable.
    d_tmp = p_inv
    del p_inv
    # Computation of d.
    np.multiply(B2, B3, d_tmp)
    d_tmp *= B3
    d -= d_tmp
    np.multiply(B4, B4, out=d_tmp)
    d_tmp *= B1
    d -= d_tmp
    np.prod(B36, axis=0, out=d_tmp)
    d_tmp *= 2
    d += d_tmp
    np.multiply(B5, B5, out=d_tmp)
    d_tmp *= B0
    d -= d_tmp
    d *= 0.5
    # Ensure -1 <= d/2 <= 1.
    np.clip(d, -1, 1, out=d)

    # Compute phi. Beware that we reuse d variable!
    phi = d
    del d
    phi = np.arccos(phi, out=phi)
    phi /= 3

    # Compute val, ordered eigenvalues. Resuing B allocation.
    del B03, B36, B0, B1, B2, B3, B4, B5

    np.add(v, phi[np.newaxis], out=val[:2])
    val[2] = phi
    np.cos(val, out=val)
    p *= 2
    val *= p
    val += q

    # Remove all variable using tmp allocation.
    del q
    del p
    del phi
    del d_tmp

    # Computing eigenvectors -- either only one or all three.
    if full:
        l = val
        vec = vec.reshape(3, 3, -1)
        vec_tmp = tmp[:3]
    else:
        l = val[0]
        vec_tmp = tmp[2]

    # Compute vec. The tmp variable can be reused.

    # u = S[4] * S[5] - (S[2] - l) * S[3]
    u = np.subtract(S[2], l, out=vec[0])
    np.multiply(u, S[3], out=u)
    u_tmp = np.multiply(S[4], S[5], out=tmp[3])
    np.subtract(u_tmp, u, out=u)
    # Put values of u into vector 2 aswell.

    # v = S[3] * S[5] - (S[1] - l) * S[4]
    v = np.subtract(S[1], l, out=vec_tmp)
    np.multiply(v, S[4], out=v)
    v_tmp = np.multiply(S[3], S[5], out=tmp[3])
    np.subtract(v_tmp, v, out=v)

    # w = S[3] * S[4] - (S[0] - l) * S[5]
    w = np.subtract(S[0], l, out=vec[2])
    np.multiply(w, S[5], out=w)
    w_tmp = np.multiply(S[3], S[4], out=tmp[3])
    np.subtract(w_tmp, w, out=w)

    vec[1] = u
    np.multiply(u, v, out=vec[0])
    u = vec[1]
    np.multiply(u, w, out=vec[1])
    np.multiply(v, w, out=vec[2])

    # Remove u, v, w and l variables.
    del u
    del v
    del w
    del l

    # Normalizing -- depends on number of vectors.
    if full:
        # vec is [x1 x2 x3, y1 y2 y3, z1 z2 z3]
        l = np.sum(np.square(vec), axis=0, out=vec_tmp)[:, np.newaxis]
        vec = np.swapaxes(vec, 0, 1)
    else:
        # vec is [x1 y1 z1] = v1
        l = np.sum(np.square(vec, out=tmp[:3]), axis=0, out=vec_tmp)

    cp.rsqrt(l, out=l)
    vec *= l

    return val.reshape(val.shape[:-1] +
                       input_shape[1:]), vec.reshape(vec.shape[:-1] +
                                                     input_shape[1:])
Esempio n. 17
0
class TestColorconv(TestCase):

    img_rgb = cp.asarray(data.colorwheel())
    img_grayscale = cp.asarray(data.camera())
    # ftm: off
    img_rgba = cp.array([[[0, 0.5, 1, 0],
                          [0, 0.5, 1, 1],
                          [0, 0.5, 1, 0.5]]]).astype(float)

    colbars = cp.array([[1, 1, 0, 0, 1, 1, 0, 0],
                        [1, 1, 1, 1, 0, 0, 0, 0],
                        [1, 0, 1, 0, 1, 0, 1, 0]]).astype(float)

    colbars_array = cp.swapaxes(colbars.reshape(3, 4, 2), 0, 2)
    colbars_point75 = colbars * 0.75
    colbars_point75_array = cp.swapaxes(colbars_point75.reshape(3, 4, 2), 0, 2)

    xyz_array = cp.asarray([[[0.4124, 0.21260, 0.01930]],    # red
                            [[0, 0, 0]],    # black
                            [[.9505, 1., 1.089]],    # white
                            [[.1805, .0722, .9505]],    # blue
                            [[.07719, .15438, .02573]],    # green
                            ])
    lab_array = cp.asarray([[[53.233, 80.109, 67.220]],    # red
                            [[0., 0., 0.]],    # black
                            [[100.0, 0.005, -0.010]],    # white
                            [[32.303, 79.197, -107.864]],    # blue
                            [[46.229, -51.7, 49.898]],    # green
                            ])

    luv_array = cp.asarray([[[53.233, 175.053, 37.751]],   # red
                            [[0., 0., 0.]],   # black
                            [[100., 0.001, -0.017]],   # white
                            [[32.303, -9.400, -130.358]],   # blue
                            [[46.228, -43.774, 56.589]],   # green
                            ])
    # ftm: on

    # RGBA to RGB
    def test_rgba2rgb_conversion(self):
        rgba = self.img_rgba
        rgb = rgba2rgb(rgba)
        # ftm: off
        expected = cp.asarray([[[1, 1, 1],
                                [0, 0.5, 1],
                                [0.5, 0.75, 1]]]).astype(float)

        # ftm: on
        self.assertEqual(rgb.shape, expected.shape)
        assert_array_almost_equal(rgb, expected)

    def test_rgba2rgb_error_grayscale(self):
        self.assertRaises(ValueError, rgba2rgb, self.img_grayscale)

    def test_rgba2rgb_error_rgb(self):
        self.assertRaises(ValueError, rgba2rgb, self.img_rgb)

    def test_rgba2rgb_dtype(self):
        rgba = self.img_rgba.astype("float64")
        rgba32 = img_as_float32(rgba)

        assert rgba2rgb(rgba).dtype == rgba.dtype
        assert rgba2rgb(rgba32).dtype == rgba32.dtype

    # RGB to HSV
    def test_rgb2hsv_conversion(self):
        rgb = img_as_float(self.img_rgb)[::16, ::16]
        hsv = rgb2hsv(rgb).reshape(-1, 3)
        # ground truth from colorsys
        gt = np.asarray([colorsys.rgb_to_hsv(pt[0], pt[1], pt[2])
                         for pt in cp.asnumpy(rgb).reshape(-1, 3)])
        assert_array_almost_equal(hsv, gt)

    def test_rgb2hsv_error_grayscale(self):
        self.assertRaises(ValueError, rgb2hsv, self.img_grayscale)

    def test_rgb2hsv_dtype(self):
        rgb = img_as_float(self.img_rgb)
        rgb32 = img_as_float32(self.img_rgb)

        assert rgb2hsv(rgb).dtype == rgb.dtype
        assert rgb2hsv(rgb32).dtype == rgb32.dtype

    # HSV to RGB
    def test_hsv2rgb_conversion(self):
        rgb = self.img_rgb.astype("float32")[::16, ::16]
        # create HSV image with colorsys
        hsv = cp.asarray(
            [
                colorsys.rgb_to_hsv(pt[0], pt[1], pt[2])
                for pt in rgb.reshape(-1, 3).get()
            ]
        ).reshape(rgb.shape)
        # convert back to RGB and compare with original.
        # relative precision for RGB -> HSV roundtrip is about 1e-6
        assert_array_almost_equal(rgb, hsv2rgb(hsv), decimal=4)

    def test_hsv2rgb_error_grayscale(self):
        self.assertRaises(ValueError, hsv2rgb, self.img_grayscale)

    def test_hsv2rgb_dtype(self):
        rgb = self.img_rgb.astype("float32")[::16, ::16]
        # create HSV image with colorsys
        hsv = cp.asarray(
            [
                colorsys.rgb_to_hsv(pt[0], pt[1], pt[2])
                for pt in rgb.reshape(-1, 3).get()
            ],
            dtype="float64",
        ).reshape(rgb.shape)
        hsv32 = hsv.astype("float32")

        assert hsv2rgb(hsv).dtype == hsv.dtype
        assert hsv2rgb(hsv32).dtype == hsv32.dtype

    # RGB to XYZ
    def test_rgb2xyz_conversion(self):
        # ftm: off
        gt = cp.asarray([[[0.950456, 1.      , 1.088754],    # noqa
                          [0.538003, 0.787329, 1.06942 ],    # noqa
                          [0.592876, 0.28484 , 0.969561],    # noqa
                          [0.180423, 0.072169, 0.950227]],   # noqa
                         [[0.770033, 0.927831, 0.138527],    # noqa
                          [0.35758 , 0.71516 , 0.119193],    # noqa
                          [0.412453, 0.212671, 0.019334],    # noqa
                          [0.      , 0.      , 0.      ]]])  # noqa
        # ftm: on
        assert_array_almost_equal(rgb2xyz(self.colbars_array), gt)

    # stop repeating the "raises" checks for all other functions that are
    # implemented with color._convert()
    def test_rgb2xyz_error_grayscale(self):
        self.assertRaises(ValueError, rgb2xyz, self.img_grayscale)

    def test_rgb2xyz_dtype(self):
        img = self.colbars_array
        img32 = img.astype('float32')

        assert rgb2xyz(img).dtype == img.dtype
        assert rgb2xyz(img32).dtype == img32.dtype

    # XYZ to RGB
    def test_xyz2rgb_conversion(self):
        assert_array_almost_equal(xyz2rgb(rgb2xyz(self.colbars_array)),
                                  self.colbars_array)

    def test_xyz2rgb_dtype(self):
        img = rgb2xyz(self.colbars_array)
        img32 = img.astype('float32')

        assert xyz2rgb(img).dtype == img.dtype
        assert xyz2rgb(img32).dtype == img32.dtype

    # RGB<->XYZ roundtrip on another image
    def test_xyz_rgb_roundtrip(self):
        img_rgb = img_as_float(self.img_rgb)
        assert_array_almost_equal(xyz2rgb(rgb2xyz(img_rgb)), img_rgb)

    # RGB<->HED roundtrip with ubyte image
    def test_hed_rgb_roundtrip(self):
        img_rgb = img_as_ubyte(self.img_rgb)
        new = img_as_ubyte(hed2rgb(rgb2hed(img_rgb)))
        assert_array_equal(new, img_rgb)

    # RGB<->HED roundtrip with float image
    def test_hed_rgb_float_roundtrip(self):
        img_rgb = img_as_float(self.img_rgb)
        assert_array_almost_equal(hed2rgb(rgb2hed(img_rgb)), img_rgb)

    # RGB<->HDX roundtrip with ubyte image
    def test_hdx_rgb_roundtrip(self):
        from cucim.skimage.color.colorconv import hdx_from_rgb, rgb_from_hdx
        img_rgb = self.img_rgb
        conv = combine_stains(separate_stains(img_rgb, hdx_from_rgb),
                              rgb_from_hdx)
        assert_array_equal(img_as_ubyte(conv), img_rgb)

    # RGB<->HDX roundtrip with float image
    def test_hdx_rgb_roundtrip_float(self):
        from cucim.skimage.color.colorconv import hdx_from_rgb, rgb_from_hdx

        img_rgb = img_as_float(self.img_rgb)
        conv = combine_stains(separate_stains(img_rgb, hdx_from_rgb),
                              rgb_from_hdx)
        assert_array_almost_equal(conv, img_rgb)

    # RGB to RGB CIE
    def test_rgb2rgbcie_conversion(self):
        # ftm: off
        gt = cp.asarray([[[ 0.1488856 ,  0.18288098,  0.19277574],    # noqa
                          [ 0.01163224,  0.16649536,  0.18948516],    # noqa
                          [ 0.12259182,  0.03308008,  0.17298223],    # noqa
                          [-0.01466154,  0.01669446,  0.16969164]],   # noqa
                         [[ 0.16354714,  0.16618652,  0.0230841 ],    # noqa
                          [ 0.02629378,  0.1498009 ,  0.01979351],    # noqa
                          [ 0.13725336,  0.01638562,  0.00329059],    # noqa
                          [ 0.        ,  0.        ,  0.        ]]])  # noqa
        # ftm: on
        assert_array_almost_equal(rgb2rgbcie(self.colbars_array), gt)

    def test_rgb2rgbcie_dtype(self):
        img = self.colbars_array.astype('float64')
        img32 = img.astype('float32')

        assert rgb2rgbcie(img).dtype == img.dtype
        assert rgb2rgbcie(img32).dtype == img32.dtype

    # RGB CIE to RGB
    def test_rgbcie2rgb_conversion(self):
        # only roundtrip test, we checked rgb2rgbcie above already
        assert_array_almost_equal(rgbcie2rgb(rgb2rgbcie(self.colbars_array)),
                                  self.colbars_array)

    def test_rgbcie2rgb_dtype(self):
        img = rgb2rgbcie(self.colbars_array).astype('float64')
        img32 = img.astype('float32')

        assert rgbcie2rgb(img).dtype == img.dtype
        assert rgbcie2rgb(img32).dtype == img32.dtype

    def test_convert_colorspace(self):
        colspaces = ['HSV', 'RGB CIE', 'XYZ', 'YCbCr', 'YPbPr', 'YDbDr']
        colfuncs_from = [
            hsv2rgb, rgbcie2rgb, xyz2rgb,
            ycbcr2rgb, ypbpr2rgb, ydbdr2rgb
        ]
        colfuncs_to = [
            rgb2hsv, rgb2rgbcie, rgb2xyz,
            rgb2ycbcr, rgb2ypbpr, rgb2ydbdr
        ]

        assert_array_almost_equal(
            convert_colorspace(self.colbars_array, 'RGB', 'RGB'),
            self.colbars_array)

        for i, space in enumerate(colspaces):
            # print(f"space={space}")
            gt = colfuncs_from[i](self.colbars_array)
            assert_array_almost_equal(
                convert_colorspace(self.colbars_array, space, 'RGB'), gt)
            gt = colfuncs_to[i](self.colbars_array)
            assert_array_almost_equal(
                convert_colorspace(self.colbars_array, 'RGB', space), gt)

        self.assertRaises(ValueError, convert_colorspace,
                          self.colbars_array, 'nokey', 'XYZ')
        self.assertRaises(ValueError, convert_colorspace,
                          self.colbars_array, 'RGB', 'nokey')

    def test_rgb2gray(self):
        x = cp.asarray([1, 1, 1]).reshape((1, 1, 3)).astype(float)
        g = rgb2gray(x)
        assert_array_almost_equal(g, 1)

        assert_array_equal(g.shape, (1, 1))

    def test_rgb2gray_contiguous(self):
        x = cp.random.rand(10, 10, 3)
        assert rgb2gray(x).flags["C_CONTIGUOUS"]
        assert rgb2gray(x[:5, :5]).flags["C_CONTIGUOUS"]

    def test_rgb2gray_alpha(self):
        x = cp.random.rand(10, 10, 4)
        with expected_warnings(['Non RGB image conversion']):
            assert rgb2gray(x).ndim == 2

    def test_rgb2gray_on_gray(self):
        with expected_warnings(['The behavior of rgb2gray will change']):
            rgb2gray(cp.random.rand(5, 5))

    def test_rgb2gray_dtype(self):
        img = cp.random.rand(10, 10, 3).astype('float64')
        img32 = img.astype('float32')

        assert rgb2gray(img).dtype == img.dtype
        assert rgb2gray(img32).dtype == img32.dtype

    # test matrices for xyz2lab and lab2xyz generated using
    # http://www.easyrgb.com/index.php?X=CALC
    # Note: easyrgb website displays xyz*100
    def test_xyz2lab(self):
        assert_array_almost_equal(xyz2lab(self.xyz_array),
                                  self.lab_array, decimal=3)

        # Test the conversion with the rest of the illuminants.
        for i in ["d50", "d55", "d65", "d75"]:
            for obs in ["2", "10"]:
                fname = "color/tests/data/lab_array_{0}_{1}.npy".format(i, obs)
                lab_array_i_obs = np.load(fetch(fname))
                assert_array_almost_equal(lab_array_i_obs,
                                          xyz2lab(self.xyz_array, i, obs),
                                          decimal=2)
        for i in ["a", "e"]:
            fname = "color/tests/data/lab_array_{0}_2.npy".format(i)
            lab_array_i_obs = np.load(fetch(fname))
            assert_array_almost_equal(lab_array_i_obs,
                                      xyz2lab(self.xyz_array, i, "2"),
                                      decimal=2)

    def test_xyz2lab_dtype(self):
        img = self.xyz_array.astype('float64')
        img32 = img.astype('float32')

        assert xyz2lab(img).dtype == img.dtype
        assert xyz2lab(img32).dtype == img32.dtype

    def test_lab2xyz(self):
        assert_array_almost_equal(lab2xyz(self.lab_array),
                                  self.xyz_array, decimal=3)

        # Test the conversion with the rest of the illuminants.
        for i in ["d50", "d55", "d65", "d75"]:
            for obs in ["2", "10"]:
                fname = "color/tests/data/lab_array_{0}_{1}.npy".format(i, obs)
                lab_array_i_obs = cp.array(np.load(fetch(fname)))
                assert_array_almost_equal(lab2xyz(lab_array_i_obs, i, obs),
                                          self.xyz_array, decimal=3)
        for i in ["a", "e"]:
            fname = "lab_array_{0}_2.npy".format(i)
            lab_array_i_obs = cp.array(
                np.load(fetch('color/tests/data/' + fname)))
            assert_array_almost_equal(lab2xyz(lab_array_i_obs, i, "2"),
                                      self.xyz_array, decimal=3)

        # And we include a call to test the exception handling in the code.
        try:
            lab2xyz(lab_array_i_obs, "Nai", "2")  # Not an illuminant
        except ValueError:
            pass

        try:
            lab2xyz(lab_array_i_obs, "d50", "42")  # Not a degree
        except ValueError:
            pass

    def test_lab2xyz_dtype(self):
        img = self.lab_array.astype('float64')
        img32 = img.astype('float32')

        assert lab2xyz(img).dtype == img.dtype
        assert lab2xyz(img32).dtype == img32.dtype

    def test_rgb2lab_brucelindbloom(self):
        """
        Test the RGB->Lab conversion by comparing to the calculator on the
        authoritative Bruce Lindbloom
        [website](http://brucelindbloom.com/index.html?ColorCalculator.html).
        """
        # Obtained with D65 white point, sRGB model and gamma
        # ftm: off
        gt_for_colbars = cp.asarray([
            [100, 0, 0],
            [97.1393, -21.5537, 94.4780],
            [91.1132, -48.0875, -14.1312],
            [87.7347, -86.1827, 83.1793],
            [60.3242, 98.2343, -60.8249],
            [53.2408, 80.0925, 67.2032],
            [32.2970, 79.1875, -107.8602],
            [0, 0, 0]]).T

        # ftm: on
        gt_array = cp.swapaxes(gt_for_colbars.reshape(3, 4, 2), 0, 2)
        assert_array_almost_equal(rgb2lab(self.colbars_array), gt_array,
                                  decimal=2)

    def test_lab_rgb_roundtrip(self):
        img_rgb = img_as_float(self.img_rgb)
        assert_array_almost_equal(lab2rgb(rgb2lab(img_rgb)), img_rgb)

    def test_rgb2lab_dtype(self):
        img = self.colbars_array.astype('float64')
        img32 = img.astype('float32')

        assert rgb2lab(img).dtype == img.dtype
        assert rgb2lab(img32).dtype == img32.dtype

    def test_lab2rgb_dtype(self):
        img = self.lab_array.astype('float64')
        img32 = img.astype('float32')

        assert lab2rgb(img).dtype == img.dtype
        assert lab2rgb(img32).dtype == img32.dtype

    # test matrices for xyz2luv and luv2xyz generated using
    # http://www.easyrgb.com/index.php?X=CALC
    # Note: easyrgb website displays xyz*100
    def test_xyz2luv(self):
        assert_array_almost_equal(xyz2luv(self.xyz_array),
                                  self.luv_array, decimal=3)

        # Test the conversion with the rest of the illuminants.
        for i in ["d50", "d55", "d65", "d75"]:
            for obs in ["2", "10"]:
                fname = "color/tests/data/luv_array_{0}_{1}.npy".format(i, obs)
                luv_array_i_obs = cp.array(np.load(fetch(fname)))
                assert_array_almost_equal(luv_array_i_obs,
                                          xyz2luv(self.xyz_array, i, obs),
                                          decimal=2)
        for i in ["a", "e"]:
            fname = "color/tests/data/luv_array_{0}_2.npy".format(i)
            luv_array_i_obs = cp.array(np.load(fetch(fname)))
            assert_array_almost_equal(luv_array_i_obs,
                                      xyz2luv(self.xyz_array, i, "2"),
                                      decimal=2)

    def test_xyz2luv_dtype(self):
        img = self.xyz_array.astype('float64')
        img32 = img.astype('float32')

        assert xyz2luv(img).dtype == img.dtype
        assert xyz2luv(img32).dtype == img32.dtype

    def test_luv2xyz(self):
        assert_array_almost_equal(luv2xyz(self.luv_array),
                                  self.xyz_array, decimal=3)

        # Test the conversion with the rest of the illuminants.
        for i in ["d50", "d55", "d65", "d75"]:
            for obs in ["2", "10"]:
                fname = "color/tests/data/luv_array_{0}_{1}.npy".format(i, obs)
                luv_array_i_obs = cp.array(np.load(fetch(fname)))
                assert_array_almost_equal(luv2xyz(luv_array_i_obs, i, obs),
                                          self.xyz_array, decimal=3)
        for i in ["a", "e"]:
            fname = "color/tests/data/luv_array_{0}_2.npy".format(i)
            luv_array_i_obs = cp.array(np.load(fetch(fname)))
            assert_array_almost_equal(luv2xyz(luv_array_i_obs, i, "2"),
                                      self.xyz_array, decimal=3)

    def test_luv2xyz_dtype(self):
        img = self.luv_array.astype('float64')
        img32 = img.astype('float32')

        assert luv2xyz(img).dtype == img.dtype
        assert luv2xyz(img32).dtype == img32.dtype

    def test_rgb2luv_brucelindbloom(self):
        """
        Test the RGB->Lab conversion by comparing to the calculator on the
        authoritative Bruce Lindbloom
        [website](http://brucelindbloom.com/index.html?ColorCalculator.html).
        """
        # Obtained with D65 white point, sRGB model and gamma
        # ftm: off
        gt_for_colbars = cp.asarray([
            [100, 0, 0],
            [97.1393, 7.7056, 106.7866],
            [91.1132, -70.4773, -15.2042],
            [87.7347, -83.0776, 107.3985],
            [60.3242, 84.0714, -108.6834],
            [53.2408, 175.0151, 37.7564],
            [32.2970, -9.4054, -130.3423],
            [0, 0, 0]]).T

        # ftm: on
        gt_array = cp.swapaxes(gt_for_colbars.reshape(3, 4, 2), 0, 2)
        assert_array_almost_equal(rgb2luv(self.colbars_array),
                                  gt_array, decimal=2)

    def test_rgb2luv_dtype(self):
        img = self.colbars_array.astype('float64')
        img32 = img.astype('float32')

        assert rgb2luv(img).dtype == img.dtype
        assert rgb2luv(img32).dtype == img32.dtype

    def test_luv2rgb_dtype(self):
        img = self.luv_array.astype('float64')
        img32 = img.astype('float32')

        assert luv2rgb(img).dtype == img.dtype
        assert luv2rgb(img32).dtype == img32.dtype

    def test_luv_rgb_roundtrip(self):
        img_rgb = img_as_float(self.img_rgb)
        assert_array_almost_equal(luv2rgb(rgb2luv(img_rgb)), img_rgb)

    def test_lab_rgb_outlier(self):
        lab_array = np.ones((3, 1, 3))
        lab_array[0] = [50, -12, 85]
        lab_array[1] = [50, 12, -85]
        lab_array[2] = [90, -4, -47]
        lab_array = cp.asarray(lab_array)
        # ftm: off
        rgb_array = cp.asarray([[[0.501, 0.481, 0]],
                                [[0, 0.482, 1.]],
                                [[0.578, 0.914, 1.]],
                                ])

        # ftm: on
        assert_array_almost_equal(lab2rgb(lab_array), rgb_array, decimal=3)

    def test_lab_full_gamut(self):
        a, b = cp.meshgrid(cp.arange(-100, 100), cp.arange(-100, 100))
        L = cp.ones(a.shape)
        lab = cp.dstack((L, a, b))
        for value in [0, 10, 20]:
            lab[:, :, 0] = value
            with expected_warnings(['Color data out of range']):
                lab2xyz(lab)

    def test_lab_lch_roundtrip(self):
        rgb = img_as_float(self.img_rgb)
        lab = rgb2lab(rgb)
        lab2 = lch2lab(lab2lch(lab))
        assert_array_almost_equal(lab2, lab)

    def test_rgb_lch_roundtrip(self):
        rgb = img_as_float(self.img_rgb)
        lab = rgb2lab(rgb)
        lch = lab2lch(lab)
        lab2 = lch2lab(lch)
        rgb2 = lab2rgb(lab2)
        assert_array_almost_equal(rgb, rgb2)

    def test_lab_lch_0d(self):
        lab0 = self._get_lab0()
        lch0 = lab2lch(lab0)
        lch2 = lab2lch(lab0[None, None, :])
        assert_array_almost_equal(lch0, lch2[0, 0, :])

    def test_lab_lch_1d(self):
        lab0 = self._get_lab0()
        lch0 = lab2lch(lab0)
        lch1 = lab2lch(lab0[None, :])
        assert_array_almost_equal(lch0, lch1[0, :])

    def test_lab_lch_3d(self):
        lab0 = self._get_lab0()
        lch0 = lab2lch(lab0)
        lch3 = lab2lch(lab0[None, None, None, :])
        assert_array_almost_equal(lch0, lch3[0, 0, 0, :])

    def _get_lab0(self):
        rgb = img_as_float(self.img_rgb[:1, :1, :])
        return rgb2lab(rgb)[0, 0, :]

    def test_yuv(self):
        rgb = cp.asarray([[[1.0, 1.0, 1.0]]])
        assert_array_almost_equal(rgb2yuv(rgb), cp.asarray([[[1, 0, 0]]]))
        assert_array_almost_equal(rgb2yiq(rgb), cp.asarray([[[1, 0, 0]]]))
        assert_array_almost_equal(rgb2ypbpr(rgb), cp.asarray([[[1, 0, 0]]]))
        assert_array_almost_equal(
            rgb2ycbcr(rgb), cp.asarray([[[235, 128, 128]]])
        )
        assert_array_almost_equal(rgb2ydbdr(rgb), cp.asarray([[[1, 0, 0]]]))
        rgb = cp.asarray([[[0.0, 1.0, 0.0]]])
        assert_array_almost_equal(
            rgb2yuv(rgb), cp.asarray([[[0.587, -0.28886916, -0.51496512]]])
        )
        assert_array_almost_equal(
            rgb2yiq(rgb), cp.asarray([[[0.587, -0.27455667, -0.52273617]]])
        )
        assert_array_almost_equal(
            rgb2ypbpr(rgb), cp.asarray([[[0.587, -0.331264, -0.418688]]])
        )
        assert_array_almost_equal(
            rgb2ycbcr(rgb), cp.asarray([[[144.553, 53.797, 34.214]]])
        )
        assert_array_almost_equal(
            rgb2ydbdr(rgb), cp.asarray([[[0.587, -0.883, 1.116]]])
        )

    def test_yuv_roundtrip(self):
        img_rgb = img_as_float(self.img_rgb)[::16, ::16]
        assert_array_almost_equal(yuv2rgb(rgb2yuv(img_rgb)), img_rgb)
        assert_array_almost_equal(yiq2rgb(rgb2yiq(img_rgb)), img_rgb)
        assert_array_almost_equal(ypbpr2rgb(rgb2ypbpr(img_rgb)), img_rgb)
        assert_array_almost_equal(ycbcr2rgb(rgb2ycbcr(img_rgb)), img_rgb)
        assert_array_almost_equal(ydbdr2rgb(rgb2ydbdr(img_rgb)), img_rgb)

    def test_rgb2yuv_dtype(self):
        img = self.colbars_array.astype('float64')
        img32 = img.astype('float32')

        assert rgb2yuv(img).dtype == img.dtype
        assert rgb2yuv(img32).dtype == img32.dtype

    def test_yuv2rgb_dtype(self):
        img = rgb2yuv(self.colbars_array).astype('float64')
        img32 = img.astype('float32')

        assert yuv2rgb(img).dtype == img.dtype
        assert yuv2rgb(img32).dtype == img32.dtype

    def test_rgb2yiq_conversion(self):
        rgb = img_as_float(self.img_rgb)[::16, ::16]
        yiq = rgb2yiq(rgb).reshape(-1, 3)
        gt = np.asarray([colorsys.rgb_to_yiq(pt[0], pt[1], pt[2])
                         for pt in cp.asnumpy(rgb).reshape(-1, 3)]
                        )
        assert_array_almost_equal(yiq, gt, decimal=2)
Esempio n. 18
0
    r3 = np.sum((z3 - mul(W3, a2) - b3) * (z3 - mul(W3, a2) - b3))
    loss = common.cross_entropy_with_softmax(y_train, z3)
    obj = loss + np.trace(mul(z3 - mul(W3, a2) - b3, np.transpose(u)))
    obj = obj + rho / 2 * r1 + rho / 2 * r2 + rho / 2 * r3
    obj = obj + rho / 2 * np.sum(
        (a1 - common.relu(z1) + v1) *
        (a1 - common.relu(z1) + v1)) + rho / 2 * np.sum(
            (a2 - common.relu(z2) + v2) * (a2 - common.relu(z2) + v2))
    return obj


mnist = mnist()
# initialization
x_train = mnist.train.xs
y_train = mnist.train.ys
x_train = np.swapaxes(x_train, 0, 1)
y_train = np.swapaxes(y_train, 0, 1)
x_train = np.array(x_train)
y_train = np.array(y_train)
x_test = mnist.test.xs
y_test = mnist.test.ys
x_test = np.swapaxes(x_test, 0, 1)
y_test = np.swapaxes(y_test, 0, 1)
x_test = np.array(x_test)
y_test = np.array(y_test)

num_of_neurons = 1000
ITER = 10000
index = 0
W1, b1, z1, a1, W2, b2, z2, a2, W3, b3, z3 = Net(x_train, y_train,
                                                 num_of_neurons)
Esempio n. 19
0
def apply(gate, states, global_phase=False):

    # A shorthand for the original states
    a = states
    # d1 = number of circuit runs with noise, d2 = 2 ** N = dimension of state vector

    d1, d2 = states.shape
    N = int(rint(log2(d2)))

    # A copy of state a, to be flipped by qubit-wise Pauli operations
    b = copy(a)

    # print("d1 = ", d1)
    # print("d2 = ", d2)
    # print("N = ", N)
    # Reshape to rank-(N+1) tensor
    b = b.reshape([d1] + [2] * N)

    for k in range(len(gate[0])):

        basis = gate[0][k]
        q = gate[1][k]

        if basis == identity:
            pass

        if basis == x:
            b = roll(b, 1, q + 1)

        if basis == y:
            b = roll(b, 1, q + 1)
            b = swapaxes(b, 0, q + 1)
            b[0] *= -1j
            b[1] *= 1j
            b = swapaxes(b, 0, q + 1)

        if basis == s_phi:
            phi = array(gate[3][k])
            b = roll(b, 1, q + 1)
            b = swapaxes(b, 0, q + 1)
            b = swapaxes(b, N, q + 1)
            phase1 = cos(phi) + 1j * sin(phi)
            phase2 = cos(phi) - 1j * sin(phi)
            b[0] = multiply(phase2, b[0])
            b[1] = multiply(phase1, b[1])
            b = swapaxes(b, N, q + 1)
            b = swapaxes(b, 0, q + 1)

        if basis == z:
            b = swapaxes(b, 0, q + 1)
            b[1] *= -1
            b = swapaxes(b, 0, q + 1)

    b = b.reshape(d1, d2)
    angles = array(gate[2][0])

    states = (cos(angles / 2) * a.T - 1j * sin(angles / 2) * b.T).T

    # Remove global phase (may be awkward if first amplitude is close to zero)

    if global_phase == False:
        pass

    return states
def compute_gradients_gpu(u, v, lr, batch_size, num_negs, dimensions, indices,
                          negatives):
    """
    This function computes and applies the gradient updates for the batch os samples, applying them inside
    the function then returning the final values that the embedding should be set too.

    :param u: the embedding values for the words we are computing gradients for (batch_size, dimensions)
    :param v: the embedding values for the positive sample + negatives samples (1 + num_negs, dimensions)
    :param lr: learning rate
    :param batch_size: size of the current batch, may vary from regular batch_size because of last remaining samples
    that can't fit into an entire batch_size in an epoch
    :param num_negs: number of negative samples for each positive sample
    :param dimensions: dimensions of the embedding
    :param indices: the indices of all the u values (batch_size)
    :param negatives: the indices of all the v values (batch_size, 1 + num_negs)
    :return: Returns the values that the embedding of the samples and negatives should be set too as well as the loss

    Once again, calculation was adapted from R. Řehůřek and P. Sojka
    RaRe-Technologies: Software Framework for Topic Modelling with Large Corpora
    https://github.com/RaRe-Technologies/gensim
    """
    u = cp.asarray(u)
    v = cp.asarray(v)
    u_orig = u
    v_orig = v
    u = u.T[cp.newaxis, :, :]
    v = cp.swapaxes(cp.swapaxes(v, 1, 2), 0, 2)
    norm_u = cp.linalg.norm(u, axis=1)
    norm_v = cp.linalg.norm(v, axis=1)
    distances = cp.linalg.norm(u - v, axis=1)
    alpha = 1 - norm_u**2
    beta = 1 - norm_v**2
    gamma = 1 + 2 * ((distances**2) / (alpha * beta))
    poincare_distances = cp.arccosh(gamma)
    exp_negative_distances = cp.exp(-poincare_distances)
    sum = cp.sum(exp_negative_distances, axis=0)

    distances_squared = distances**2
    c = (4 / (alpha * beta * cp.sqrt(gamma**2 - 1)))[:, cp.newaxis, :]
    u_coeff = ((distances_squared + alpha) / alpha)[:, cp.newaxis, :]
    distance_gradient_u = (u_coeff * u - v)
    distance_gradient_u *= c

    v_coeffs = ((distances_squared + beta) / beta)[:, cp.newaxis, :]
    distance_gradients_v = (v_coeffs * v - u)
    distance_gradients_v *= c

    gradients_v = -exp_negative_distances[:,
                                          cp.newaxis, :] * distance_gradients_v
    gradients_v /= sum
    gradients_v[0] += distance_gradients_v[0]
    gradients_v[0] += lr * 2 * v[0]

    gradients_u = -exp_negative_distances[:,
                                          cp.newaxis, :] * distance_gradient_u
    gradients_u /= sum
    gradient_u = cp.sum(gradients_u, axis=0)
    gradient_u += distance_gradient_u[0]

    u_update = (lr * (alpha**2) / 4 * gradient_u).T
    handle_duplicates(u_update, indices)
    v_updates = cp.swapaxes(
        cp.swapaxes((lr * (beta**2)[:, cp.newaxis, :] / 4 * gradients_v), 0,
                    2), 1, 2)
    v_updates = cp.reshape(v_updates,
                           (batch_size * (num_negs + 1), dimensions))
    handle_duplicates(v_updates, np.ravel(negatives))

    u_orig -= u_update
    v_orig = cp.reshape(v_orig, (batch_size * (num_negs + 1), dimensions))
    v_orig -= v_updates
    u_norms = cp.linalg.norm(u_orig, axis=1)
    v_norms = cp.linalg.norm(v_orig, axis=1)

    u_orig = (u_norms >= 1 - epsilon)[:, cp.newaxis] * (
        u_orig / u_norms[:, cp.newaxis] - cp.sign(u_orig) * 0.00001) + (
            u_norms < 1 - epsilon)[:, cp.newaxis] * u_orig

    v_orig = (v_norms >= 1 - epsilon)[:, cp.newaxis] * (
        v_orig / v_norms[:, cp.newaxis] - cp.sign(v_orig) * 0.00001) + (
            v_norms < 1 - epsilon)[:, cp.newaxis] * v_orig

    loss = cp.sum(-cp.log(exp_negative_distances[0] / sum), axis=0)
    return u_orig, v_orig, loss
Esempio n. 21
0
    def transform(self, images):
        """
        Parameters
        ----------
        images: np.ndarray
            | Color / grayscale images of shape
            | (n_images, height, width, n_channels) or
            | (n_images, height, width)

        Returns
        -------
        X: np.ndarray
            A set of feature vectors of shape (n_images, n_features)
            where :code:`n_features` is determined by the hyperparameters
        """
        images = self.process_input(images)
        # images.shape == (n_images, n_channels, y, x)

        filters_l1 = components_to_filters(
            self.pca_l1.components_,
            n_channels=images.shape[1],
            filter_shape=self.filter_shape_l1,
        )

        filters_l2 = components_to_filters(
            self.pca_l2.components_,
            n_channels=1,
            filter_shape=self.filter_shape_l2
        )

        if gpu_enabled():
            images = to_gpu(images)
            filters_l1 = to_gpu(filters_l1)
            filters_l2 = to_gpu(filters_l2)

        images = convolution_2d(
            images,
            filters_l1,
            stride=self.step_shape_l1
        ).data

        images = xp.swapaxes(images, 0, 1)

        # L1.shape == (L1, n_images, y, x)
        # iterate over each L1 output

        X = []
        for maps in images:
            n_images, h, w = maps.shape
            maps = convolution_2d(
                maps.reshape(n_images, 1, h, w),  # 1 channel images
                filters_l2,
                stride=self.step_shape_l2
            ).data

            # maps.shape == (n_images, L2, y, x) right here
            maps = binarize(maps)
            maps = binary_to_decimal(maps)
            # maps.shape == (n_images, y, x)
            x = self.histogram(maps)

            # x is a set of feature vectors.
            # The shape of x is (n_images, vector length)

            #JCG comment: histogram length is pow(2, L2), i.e. the range
            #of integers that can be represented by the binarized outputs of 
            #L2 filters so we normally have shape (n_images, 256)
            X.append(x)

        #JCG comment: X contains L1 elements of shape (n_images, 256)

        # concatenate over L1
        X = xp.hstack(X)
        #JCG comment: now X contains n_images elements of shape (L1*256)

        if gpu_enabled():
            X = to_cpu(X)

        X = X.astype(np.float64)

        # The shape of X is (n_images, L1 * vector length)
        return X
Esempio n. 22
0
def display(a):
    surf = pygame.surfarray.make_surface(
        cp.asnumpy(
            upsample((cp.flip(cp.flip(cp.swapaxes(a, 0, 1), 1), 0) * 255))))
    disp.blit(surf, (0, 0))
Esempio n. 23
0
    def transform(self, images):
        """
        Parameters
        ----------
        image: np.ndarray
            | Color / grayscale image of shape
            | (height, width, n_channels) or
            | (height, width)

        Returns
        -------
        X: np.ndarray
            A set of feature vectors of shape (n_images, n_features)
            where :code:`n_features` is determined by the hyperparameters
            
        
        NB: It is necessary to call the fit function first, to set the filters.
        """

        #images.shape == (1, h, w[, n_channels])
        images = self.process_input(images)
        #Now images.shape == (1, n_channels=1, y, x)

        #Retrieve the layer 1 filters
        filters_l1 = pcanet.components_to_filters(
            self.pca_l1.components_,
            n_channels=images.shape[1],
            filter_shape=self.filter_shape_l1,
        )

        #Retrieve the layer 2 filters
        filters_l2 = pcanet.components_to_filters(
            self.pca_l2.components_,
            n_channels=1,
            filter_shape=self.filter_shape_l2)

        if gpu_enabled():
            images = to_gpu(images)
            filters_l1 = to_gpu(filters_l1)
            filters_l2 = to_gpu(filters_l2)

        #Apply the layer 1 filters
        l1output = convolution_2d(images,
                                  filters_l1,
                                  stride=self.step_shape_l1,
                                  pad=1).data

        #The l1 output has shape (n_images, L1, y, x), swap axes
        l1output = xp.swapaxes(l1output, 0, 1)

        # Now l1output.shape == (L1, n_images, y, x)
        # iterate over each L1 output, applying L2 filters
        l2output = []
        for maps in l1output:
            n_images, h, w = maps.shape
            l2maps = convolution_2d(
                maps.reshape(n_images, 1, h, w),  # 1 channel images
                filters_l2,
                stride=self.step_shape_l2,
                pad=1).data

            # l2maps.shape == (n_images, L2, y, x)
            # Apply sigmoid and sum over the L2 channels
            Z = np.zeros((n_images, *l2maps.shape[2:]))
            for chan in range(l2maps.shape[1]):
                Z += pow(2, 8 - chan) * (
                    expit(self.alpha * np.abs(l2maps[:, chan, ...])) - self.S0)

            l2output.append(Z)

        #JCG comment: l2output contains L1 elements of shape (n_images, h, w)

        if gpu_enabled():
            l2output = to_cpu(l2output)

        return images, l1output, l2output
Esempio n. 24
0
  async def test_blocked_cholesky():
    logger.debug("Block size=", block_size, " and total array size=", n)
    assert not n % block_size

    logger.debug("Random number generate..")
    np.random.seed(10)
    # Construct input data
    a = np.random.rand(n, n)
    a = a @ a.T
    logger.debug("Random number generate done..")
    logger.debug("Copy a to a1..")
    # Copy and layout input
    a1 = a.copy()
    logger.debug("Copying done..")
    logger.debug("Shaping starts..")
    a1 = a1.reshape(n // block_size, block_size, n // block_size, block_size).swapaxes(1,2)
    logger.debug("Shaping done..")

    logger.debug("Allocate memory..")
    for i in range(num_tests):
      global gpu_arrs
      gpu_arrs = []
      for d in range(num_gpus):
        row_size = n // (block_size * num_gpus)
        if d < ((n / block_size) % num_gpus):
          row_size += 1
        if row_size > 0:
          allocate_gpu_memory(d, row_size, n, block_size)
      logger.debug("Allocate memory done..")

      set_gpu_memory_from_cpu(a1, num_gpus)

      for i in range(len(gpu_arrs)):
        logger.debug("Device ", i, " arrays are on ", gpu_arrs[i].device);

      logger.debug("Calculate starts..")
      start = time.perf_counter()

      # Call Parla Cholesky result and wait for completion
      await cholesky_blocked_inplace(a1.shape, num_gpus)

      end = time.perf_counter()
      print(end - start, "seconds")
      logger.debug("Calculate done..")

      for i in range(len(gpu_arrs)):
        logger.debug("Device ", i, " arrays are on ", gpu_arrs[i].device);

      for d in range(len(gpu_arrs)):
        logger.debug("Device:", d, " swap array..")
        gpu_arrs[d] = cp.swapaxes(gpu_arrs[d], 2, 1)
        logger.debug("Device:", d, " swap done..")

      cpu_arrs = np.empty([n // block_size,
                           block_size,
                           n // block_size,
                           block_size], dtype=float)
      for r_num in range(n // block_size):
        dev_id   = r_num % num_gpus
        local_id = r_num // num_gpus
        cpu_arrs[r_num] = cp.asnumpy(gpu_arrs[dev_id][local_id])
      cpu_arrs = cpu_arrs.reshape(n, n)
      print("Truth", linalg.cholesky(a).T)

      # Check result
      computed_L = np.tril(cpu_arrs)
      print("Soln", computed_L)
      error = np.max(np.absolute(a-computed_L @ computed_L.T))
      print("Error", error)
      assert(error < 1E-8)
      del gpu_arrs
Esempio n. 25
0
def matrix_transpose(x: Array, /) -> Array:
    if x.ndim < 2:
        raise ValueError(
            "x must be at least 2-dimensional for matrix_transpose")
    return Array._new(np.swapaxes(x._array, -1, -2))
Esempio n. 26
0
 def test_swapaxes_failure(self):
     a = testing.shaped_arange((2, 3, 4))
     with self.assertRaises(ValueError):
         cupy.swapaxes(a, 3, 0)
Esempio n. 27
0
    def transform(self, images):
        """
        Parameters
        ----------
        images: np.ndarray
            | Color / grayscale images of shape
            | (n_images, height, width, n_channels) or
            | (n_images, height, width)

        Returns
        -------
        X: np.ndarray
            A set of feature vectors of shape (n_images, n_features)
            where :code:`n_features` is determined by the hyperparameters
        """
        print("Shape of the data passed to transform")
        print(images.shape)
        images = self.process_input(images)
        # images.shape == (n_images, n_channels, y, x)

        filters_l1 = components_to_filters(
            self.pca_l1.components_,
            n_channels=images.shape[1],
            filter_shape=self.filter_shape_l1,
        )

        filters_l2 = components_to_filters(self.pca_l2.components_,
                                           n_channels=1,
                                           filter_shape=self.filter_shape_l2)
        print("Filters in layer 2")
        print(filters_l2)
        if gpu_enabled():
            images = to_gpu(images)
            filters_l1 = to_gpu(filters_l1)
            filters_l2 = to_gpu(filters_l2)

        images = convolution_2d(images, filters_l1,
                                stride=self.step_shape_l1).data

        images = xp.swapaxes(images, 0, 1)

        # L1.shape == (L1, n_images, y, x)
        # iterate over each L1 output

        X = []
        for maps in images:
            n_images, h, w = maps.shape
            maps = convolution_2d(
                maps.reshape(n_images, 1, h, w),  # 1 channel images
                filters_l2,
                stride=self.step_shape_l2).data

            # maps.shape == (n_images, L2, y, x) right here
            maps = binarize(maps)
            maps = binary_to_decimal(maps)
            # maps.shape == (n_images, y, x)
            x = self.histogram(maps)

            # x is a set of feature vectors.
            # The shape of x is (n_images, vector length)
            X.append(x)

        # concatenate over L1
        X = xp.hstack(X)

        if gpu_enabled():
            X = to_cpu(X)

        X = X.astype(np.float64)

        # The shape of X is (n_images, L1 * vector length)
        return X
Esempio n. 28
0
def remove_global_phase(states):
    gp = exp(-1j * angle(states[0]))
    c = swapaxes(states, 0, 1)
    states = multiply(gp.T, c).T
    return states