def test_Norm(self): print ("test_BlockOperator") ## numpy.random.seed(1) N, M = 200, 300 ig = ImageGeometry(N, M) G = Gradient(ig) t0 = timer() norm = G.norm() t1 = timer() norm2 = G.norm() t2 = timer() norm3 = G.norm(force=True) t3 = timer() print ("Norm dT1 {} dT2 {} dT3 {}".format(t1-t0,t2-t1, t3-t2)) self.assertLess(t2-t1, t1-t0) self.assertLess(t2-t1, t3-t2) numpy.random.seed(1) t4 = timer() norm4 = G.norm(iterations=50, force=True) t5 = timer() self.assertLess(t2-t1, t5-t4) numpy.random.seed(1) t4 = timer() norm5 = G.norm(x_init=ig.allocate('random'), iterations=50, force=True) t5 = timer() self.assertLess(t2-t1, t5-t4) for n in [norm, norm2, norm3, norm4, norm5]: print ("norm {}", format(n))
def test_FISTA_Norm2Sq(self): print ("Test FISTA Norm2Sq") ig = ImageGeometry(127,139,149) b = ig.allocate(ImageGeometry.RANDOM) # fill with random numbers x_init = ig.allocate(ImageGeometry.RANDOM) identity = Identity(ig) #### it seems FISTA does not work with Nowm2Sq norm2sq = LeastSquares(identity, b) #norm2sq.L = 2 * norm2sq.c * identity.norm()**2 #norm2sq = FunctionOperatorComposition(L2NormSquared(b=b), identity) opt = {'tol': 1e-4, 'memopt':False} print ("initial objective", norm2sq(x_init)) alg = FISTA(x_init=x_init, f=norm2sq, g=ZeroFunction()) alg.max_iteration = 2 alg.run(20, verbose=True) self.assertNumpyArrayAlmostEqual(alg.x.as_array(), b.as_array()) alg = FISTA(x_init=x_init, f=norm2sq, g=ZeroFunction(), max_iteration=2, update_objective_interval=3) self.assertTrue(alg.max_iteration == 2) self.assertTrue(alg.update_objective_interval== 3) alg.run(20, verbose=True) self.assertNumpyArrayAlmostEqual(alg.x.as_array(), b.as_array())
def stest_NestedBlockDataContainer2(self): M, N = 2, 3 ig = ImageGeometry(voxel_num_x=M, voxel_num_y=N) ag = ig u = ig.allocate(1) op1 = Gradient(ig) op2 = Identity(ig, ag) operator = BlockOperator(op1, op2, shape=(2, 1)) d1 = op1.direct(u) d2 = op2.direct(u) d = operator.direct(u) dd = operator.domain_geometry() ww = operator.range_geometry() print(d.get_item(0).get_item(0).as_array()) print(d.get_item(0).get_item(1).as_array()) print(d.get_item(1).as_array()) c1 = d + d c2 = 2 * d c3 = d / (d + 0.0001) c5 = d.get_item(0).power(2).sum()
def test_mixedL12Norm(self): M, N, K = 2, 3, 5 ig = ImageGeometry(voxel_num_x=M, voxel_num_y=N) u1 = ig.allocate('random_int') u2 = ig.allocate('random_int') U = BlockDataContainer(u1, u2, shape=(2, 1)) # Define no scale and scaled f_no_scaled = MixedL21Norm() f_scaled = 1 * MixedL21Norm() # call a1 = f_no_scaled(U) a2 = f_scaled(U) self.assertNumpyArrayAlmostEqual(a1, a2) tmp = [el**2 for el in U.containers] self.assertBlockDataContainerEqual(BlockDataContainer(*tmp), U.power(2)) z1 = f_no_scaled.proximal_conjugate(U, 1) u3 = ig.allocate('random_int') u4 = ig.allocate('random_int') z3 = BlockDataContainer(u3, u4, shape=(2, 1)) f_no_scaled.proximal_conjugate(U, 1, out=z3) self.assertBlockDataContainerEqual(z3, z1)
def test_GradientDescentArmijo(self): print ("Test GradientDescent") ig = ImageGeometry(12,13,14) x_init = ig.allocate() # b = x_init.copy() # fill with random numbers # b.fill(numpy.random.random(x_init.shape)) b = ig.allocate('random') identity = Identity(ig) norm2sq = LeastSquares(identity, b) rate = None alg = GradientDescent(x_init=x_init, objective_function=norm2sq, rate=rate) alg.max_iteration = 100 alg.run() self.assertNumpyArrayAlmostEqual(alg.x.as_array(), b.as_array()) alg = GradientDescent(x_init=x_init, objective_function=norm2sq, max_iteration=20, update_objective_interval=2) #alg.max_iteration = 20 self.assertTrue(alg.max_iteration == 20) self.assertTrue(alg.update_objective_interval==2) alg.run(20, verbose=True) self.assertNumpyArrayAlmostEqual(alg.x.as_array(), b.as_array())
def test_FISTA_catch_Lipschitz(self): print ("Test FISTA catch Lipschitz") ig = ImageGeometry(127,139,149) x_init = ImageData(geometry=ig) x_init = ig.allocate() b = x_init.copy() # fill with random numbers b.fill(numpy.random.random(x_init.shape)) x_init = ig.allocate(ImageGeometry.RANDOM) identity = Identity(ig) #### it seems FISTA does not work with Nowm2Sq norm2sq = LeastSquares(identity, b) print ('Lipschitz', norm2sq.L) norm2sq.L = None #norm2sq.L = 2 * norm2sq.c * identity.norm()**2 #norm2sq = FunctionOperatorComposition(L2NormSquared(b=b), identity) opt = {'tol': 1e-4, 'memopt':False} print ("initial objective", norm2sq(x_init)) try: alg = FISTA(x_init=x_init, f=norm2sq, g=ZeroFunction()) self.assertTrue(False) except ValueError as ve: print (ve) self.assertTrue(True)
def test_ScaledOperator(self): print ("test_ScaledOperator") ig = ImageGeometry(10,20,30) img = ig.allocate() scalar = 0.5 sid = scalar * Identity(ig) numpy.testing.assert_array_equal(scalar * img.as_array(), sid.direct(img).as_array())
def test_CGLS(self): print ("Test CGLS") #ig = ImageGeometry(124,153,154) ig = ImageGeometry(10,2) numpy.random.seed(2) x_init = ig.allocate(0.) b = ig.allocate('random') # b = x_init.copy() # fill with random numbers # b.fill(numpy.random.random(x_init.shape)) # b = ig.allocate() # bdata = numpy.reshape(numpy.asarray([i for i in range(20)]), (2,10)) # b.fill(bdata) identity = Identity(ig) alg = CGLS(x_init=x_init, operator=identity, data=b) alg.max_iteration = 200 alg.run(20, verbose=True) self.assertNumpyArrayAlmostEqual(alg.x.as_array(), b.as_array()) alg = CGLS(x_init=x_init, operator=identity, data=b, max_iteration=200, update_objective_interval=2) self.assertTrue(alg.max_iteration == 200) self.assertTrue(alg.update_objective_interval==2) alg.run(20, verbose=True) self.assertNumpyArrayAlmostEqual(alg.x.as_array(), b.as_array())
def test_max(self): print ("test max") ig = ImageGeometry(10,10) a = numpy.asarray(numpy.linspace(-10,10, num=100, endpoint=True), dtype=numpy.float32) a = a.reshape((10,10)) d1 = ig.allocate(1) d1.fill(a) self.assertAlmostEqual(d1.max(), 10.)
def testwriteImageData(self): im_size = 5 ig = ImageGeometry(voxel_num_x = im_size, voxel_num_y = im_size) im = ig.allocate() writer = NEXUSDataWriter() writer.set_up(file_name = os.path.join(os.getcwd(), 'test_nexus_im.nxs'), data_container = im) writer.write_file() self.stestreadImageData()
def test_axpby(self): print ("test axpby") ig = ImageGeometry(10,10) d1 = ig.allocate(1) d2 = ig.allocate(2) out = ig.allocate(None) # equals to 2 * [1] + 1 * [2] = [4] d1.axpby(2,1,d2,out) res = numpy.ones_like(d1.as_array()) * 4. numpy.testing.assert_array_equal(res, out.as_array())
def skiptest_BlockDataContainerShapeArithmetic(self): print("test block data container") ig0 = ImageGeometry(2, 3, 4) ig1 = ImageGeometry(2, 3, 4) data0 = ImageData(geometry=ig0) data1 = ImageData(geometry=ig1) + 1 data2 = ImageData(geometry=ig0) + 2 data3 = ImageData(geometry=ig1) + 3 cp0 = BlockDataContainer(data0, data1) #cp1 = BlockDataContainer(data2,data3) cp1 = cp0 + 1 self.assertTrue(cp1.shape == cp0.shape) cp1 = cp0.T + 1 transpose_shape = (cp0.shape[1], cp0.shape[0]) self.assertTrue(cp1.shape == transpose_shape) cp1 = cp0.T - 1 transpose_shape = (cp0.shape[1], cp0.shape[0]) self.assertTrue(cp1.shape == transpose_shape) cp1 = (cp0.T + 1) * 2 transpose_shape = (cp0.shape[1], cp0.shape[0]) self.assertTrue(cp1.shape == transpose_shape) cp1 = (cp0.T + 1) / 2 transpose_shape = (cp0.shape[1], cp0.shape[0]) self.assertTrue(cp1.shape == transpose_shape) cp1 = cp0.T.power(2.2) transpose_shape = (cp0.shape[1], cp0.shape[0]) self.assertTrue(cp1.shape == transpose_shape) cp1 = cp0.T.maximum(3) transpose_shape = (cp0.shape[1], cp0.shape[0]) self.assertTrue(cp1.shape == transpose_shape) cp1 = cp0.T.abs() transpose_shape = (cp0.shape[1], cp0.shape[0]) self.assertTrue(cp1.shape == transpose_shape) cp1 = cp0.T.sign() transpose_shape = (cp0.shape[1], cp0.shape[0]) self.assertTrue(cp1.shape == transpose_shape) cp1 = cp0.T.sqrt() transpose_shape = (cp0.shape[1], cp0.shape[0]) self.assertTrue(cp1.shape == transpose_shape) cp1 = cp0.T.conjugate() transpose_shape = (cp0.shape[1], cp0.shape[0]) self.assertTrue(cp1.shape == transpose_shape)
def test_Identity(self): print ("test_Identity") ig = ImageGeometry(10,20,30) img = ig.allocate() # img.fill(numpy.ones((30,20,10))) self.assertTrue(img.shape == (30,20,10)) #self.assertEqual(img.sum(), 2*float(10*20*30)) self.assertEqual(img.sum(), 0.) Id = Identity(ig) y = Id.direct(img) numpy.testing.assert_array_equal(y.as_array(), img.as_array())
def setUp(self): N, M = 20, 30 K = 20 C = 20 self.decimal = 1 self.iterations = 50 ########################################################################### # 2D geometry no channels self.ig = ImageGeometry(N, M) self.ig2 = ImageGeometry(N, M, channels = C) self.ig3 = ImageGeometry(N, M, K)
def test_IndicatorBox(self): ig = ImageGeometry(10, 10) im = ig.allocate(-1) ib = IndicatorBox(lower=0) a = ib(im) numpy.testing.assert_equal(a, numpy.inf) ib = IndicatorBox(lower=-2) a = ib(im) numpy.testing.assert_array_equal(0, a) ib = IndicatorBox(lower=-5, upper=-2) a = ib(im) numpy.testing.assert_equal(a, numpy.inf)
def setUp(self): self.ig = ImageGeometry(1, 2, 3, channels=4) angles = numpy.asarray([90., 0., -90.], dtype=numpy.float32) self.ag = AcquisitionGeometry('cone', 'edo', pixel_num_h=20, pixel_num_v=2, angles=angles, dist_source_center=312.2, dist_center_detector=123., channels=4)
def __init__(self, geomv, geomp, default=False): super(CCPiProjectorSimple, self).__init__() # Store volume and sinogram geometries. self.acquisition_geometry = geomp self.volume_geometry = geomv if geomp.geom_type == "cone": raise TypeError('Can only handle parallel beam') # set-up the geometries if compatible geoms = setupCCPiGeometries(geomv, geomp, 0) vg = ImageGeometry(voxel_num_x=geoms['output_volume_x'], voxel_num_y=geoms['output_volume_y'], voxel_num_z=geoms['output_volume_z']) pg = AcquisitionGeometry('parallel', '3D', geomp.angles, geoms['n_h'], geomp.pixel_size_h, geoms['n_v'], geomp.pixel_size_v #2D in 3D is a slice 1 pixel thick ) if not default: # check if geometry is the same (on the voxels) if not ( vg.voxel_num_x == geomv.voxel_num_x and \ vg.voxel_num_y == geomv.voxel_num_y and \ vg.voxel_num_z == geomv.voxel_num_z ): msg = 'The required volume geometry will not work\nThe following would\n' msg += vg.__str__() raise ValueError(msg) if not (pg.pixel_num_h == geomp.pixel_num_h and \ pg.pixel_num_v == geomp.pixel_num_v and \ len( pg.angles ) == len( geomp.angles ) ) : msg = 'The required acquisition geometry will not work\nThe following would\n' msg += pg.__str__() raise ValueError(msg) self.fp = CCPiForwardProjector(image_geometry=vg, acquisition_geometry=pg, output_axes_order=['angle','vertical','horizontal']) self.bp = CCPiBackwardProjector(image_geometry=vg, acquisition_geometry=pg, output_axes_order=[ ImageGeometry.HORIZONTAL_X, ImageGeometry.HORIZONTAL_Y, ImageGeometry.VERTICAL]) # Initialise empty for singular value. self.s1 = None self.ag = pg self.vg = vg
def test_axpby2(self): print ("test axpby2") N = 100 ig = ImageGeometry(N,2*N,N*10) d1 = ig.allocate(1) d2 = ig.allocate(2) out = ig.allocate(None) print ("allocated") # equals to 2 * [1] + 1 * [2] = [4] d1.axpby(2,1,d2,out, num_threads=4) print ("calculated") res = numpy.ones_like(d1.as_array()) * 4. numpy.testing.assert_array_equal(res, out.as_array())
def stestreadImageData(self): im_size = 5 ig_test = ImageGeometry(voxel_num_x = im_size, voxel_num_y = im_size) im_test = ig_test.allocate() reader = NEXUSDataReader() reader.set_up(nexus_file = os.path.join(os.getcwd(), 'test_nexus_im.nxs')) im = reader.load_data() ig = reader.get_geometry() numpy.testing.assert_array_equal(im.as_array(), im_test.as_array(), 'Loaded image is not correct') self.assertEqual(ig.voxel_num_x, ig_test.voxel_num_x, 'ImageGeometry is not correct') self.assertEqual(ig.voxel_num_y, ig_test.voxel_num_y, 'ImageGeometry is not correct')
def skiptest_BlockDataContainerShape(self): print("test block data container") ig0 = ImageGeometry(12, 42, 55, 32) ig1 = ImageGeometry(12, 42, 55, 32) data0 = ImageData(geometry=ig0) data1 = ImageData(geometry=ig1) + 1 data2 = ImageData(geometry=ig0) + 2 data3 = ImageData(geometry=ig1) + 3 cp0 = BlockDataContainer(data0, data1) cp1 = BlockDataContainer(data2, data3) transpose_shape = (cp0.shape[1], cp0.shape[0]) self.assertTrue(cp0.T.shape == transpose_shape)
def test_ImageGeometry_allocate(self): vgeometry = ImageGeometry(voxel_num_x=4, voxel_num_y=3, channels=2) image = vgeometry.allocate() self.assertEqual(0,image.as_array()[0][0][0]) image = vgeometry.allocate(1) self.assertEqual(1,image.as_array()[0][0][0]) default_order = ['channel' , 'horizontal_y' , 'horizontal_x'] self.assertEqual(default_order[0], image.dimension_labels[0]) self.assertEqual(default_order[1], image.dimension_labels[1]) self.assertEqual(default_order[2], image.dimension_labels[2]) order = [ 'horizontal_x' , 'horizontal_y', 'channel' ] image = vgeometry.allocate(0,dimension_labels=order) self.assertEqual(order[0], image.dimension_labels[0]) self.assertEqual(order[1], image.dimension_labels[1]) self.assertEqual(order[2], image.dimension_labels[2])
def test_NestedBlockDataContainer(self): ig0 = ImageGeometry(2, 3, 4) ig1 = ImageGeometry(2, 3, 5) data0 = ig0.allocate(0) data2 = ig0.allocate(1) cp0 = BlockDataContainer(data0, data2) #cp1 = BlockDataContainer(data2,data3) nested = BlockDataContainer(cp0, data2, data2) out = BlockDataContainer(BlockDataContainer(data0, data0), data0, data0) nested.divide(data2, out=out) self.assertBlockDataContainerEqual(out, nested)
def test_Function(self): N = 3 ig = ImageGeometry(N, N) ag = ig op1 = Gradient(ig) op2 = Identity(ig, ag) # Form Composite Operator operator = BlockOperator(op1, op2, shape=(2, 1)) # Create functions noisy_data = ag.allocate(ImageGeometry.RANDOM_INT) d = ag.allocate(ImageGeometry.RANDOM_INT) alpha = 0.5 # scaled function g = alpha * L2NormSquared(b=noisy_data) # Compare call of g a2 = alpha * (d - noisy_data).power(2).sum() #print(a2, g(d)) self.assertEqual(a2, g(d)) # Compare convex conjugate of g a3 = 0.5 * d.squared_norm() + d.dot(noisy_data) self.assertEqual(a3, g.convex_conjugate(d))
def test_Gradient_linearity(self): nc, nz, ny, nx = 3, 4, 5, 6 ig = ImageGeometry(voxel_num_x=nx, voxel_num_y=ny, voxel_num_z=nz, channels=nc) grad = Gradient(ig, bnd_cond='Neumann', correlation='SpaceChannels', backend='c') self.assertTrue(LinearOperator.dot_test(grad)) grad = Gradient(ig, bnd_cond='Periodic', correlation='SpaceChannels', backend='c') self.assertTrue(LinearOperator.dot_test(grad)) grad = Gradient(ig, bnd_cond='Neumann', correlation='SpaceChannels', backend='numpy') self.assertTrue(LinearOperator.dot_test(grad)) grad = Gradient(ig, bnd_cond='Periodic', correlation='SpaceChannels', backend='numpy') self.assertTrue(LinearOperator.dot_test(grad))
def test_PowerMethod(self): print ("test_BlockOperator") N, M = 200, 300 niter = 10 ig = ImageGeometry(N, M) Id = Identity(ig) G = Gradient(ig) uid = Id.domain_geometry().allocate(ImageGeometry.RANDOM_INT, seed=1) a = LinearOperator.PowerMethod(Id, niter, uid) #b = LinearOperator.PowerMethodNonsquare(Id, niter, uid) b = LinearOperator.PowerMethod(Id, niter) print ("Edo impl", a[0]) print ("None impl", b[0]) #self.assertAlmostEqual(a[0], b[0]) self.assertNumpyArrayAlmostEqual(a[0],b[0],decimal=6) a = LinearOperator.PowerMethod(G, niter, uid) b = LinearOperator.PowerMethod(G, niter) #b = LinearOperator.PowerMethodNonsquare(G, niter, uid) print ("Edo impl", a[0]) #print ("old impl", b[0]) self.assertNumpyArrayAlmostEqual(a[0],b[0],decimal=2)
def process(self): projections = self.get_input() projections_axes = projections.get_data_axes_order(new_order=self.default_acquisition_axes_order) if not projections_axes == [0,1,2]: projections.array = numpy.transpose(projections.array, projections_axes) pixel_per_voxel = 1 # should be estimated from image_geometry and acquisition_geometry image_geometry = ImageGeometry(voxel_num_x = self.acquisition_geometry.pixel_num_h, voxel_num_y = self.acquisition_geometry.pixel_num_h, voxel_num_z = self.acquisition_geometry.pixel_num_v) # input centered/padded acquisitiondata center_of_rotation = projections.get_dimension_size('horizontal') / 2 if self.acquisition_geometry.geom_type == 'parallel': back = pbalg.pb_backward_project( projections.as_array(), self.acquisition_geometry.angles, center_of_rotation, pixel_per_voxel ) out = ImageData(geometry=self.image_geometry, dimension_labels=self.default_image_axes_order) out_axes = out.get_data_axes_order(new_order=self.output_axes_order) if not out_axes == [0,1,2]: back = numpy.transpose(back, out_axes) out.fill(back) return out else: raise ValueError('Cannot process cone beam')
def test_BlockOperatorLinearValidity(self): print ("test_BlockOperatorLinearValidity") M, N = 3, 4 ig = ImageGeometry(M, N) arr = ig.allocate('random_int') G = Gradient(ig) Id = Identity(ig) B = BlockOperator(G, Id) # Nx1 case u = ig.allocate('random_int') w = B.range_geometry().allocate(ImageGeometry.RANDOM_INT) w1 = B.direct(u) u1 = B.adjoint(w) self.assertEqual((w * w1).sum() , (u1*u).sum())
def test_axpby(self): # test axpby between BlockDataContainers ig0 = ImageGeometry(2, 3, 4) ig1 = ImageGeometry(2, 3, 5) data0 = ig0.allocate(-1) data2 = ig0.allocate(1) data1 = ig0.allocate(2) data3 = ig0.allocate(3) cp0 = BlockDataContainer(data0, data2) cp1 = BlockDataContainer(data1, data3) out = cp0 * 0. - 10 cp0.axpby(3, -2, cp1, out, num_threads=4) # operation should be [ 3 * -1 + (-2) * 2 , 3 * 1 + (-2) * 3 ] # output should be [ -7 , -3 ] res0 = ig0.allocate(-7) res2 = ig0.allocate(-3) res = BlockDataContainer(res0, res2) print("res0", res0.as_array()) print("res2", res2.as_array()) print("###############################") print("out_0", out.get_item(0).as_array()) print("out_1", out.get_item(1).as_array()) self.assertBlockDataContainerEqual(out, res)
def test_Norm2sq_as_FunctionOperatorComposition(self): print('Test for FunctionOperatorComposition') M, N = 50, 50 ig = ImageGeometry(voxel_num_x=M, voxel_num_y=N) b = ig.allocate('random_int') print('Check call with Identity operator... OK\n') operator = 3 * Identity(ig) u = ig.allocate('random_int', seed=50) func1 = FunctionOperatorComposition(0.5 * L2NormSquared(b=b), operator) func2 = LeastSquares(operator, b, 0.5) self.assertNumpyArrayAlmostEqual(func1(u), func2(u)) print('Check gradient with Identity operator... OK\n') tmp1 = ig.allocate() tmp2 = ig.allocate() res_gradient1 = func1.gradient(u) res_gradient2 = func2.gradient(u) func1.gradient(u, out=tmp1) func2.gradient(u, out=tmp2) self.assertNumpyArrayAlmostEqual(tmp1.as_array(), tmp2.as_array()) self.assertNumpyArrayAlmostEqual(res_gradient1.as_array(), res_gradient2.as_array()) print('Check call with LinearOperatorMatrix... OK\n') mat = np.random.randn(M, N) operator = LinearOperatorMatrix(mat) vg = VectorGeometry(N) b = vg.allocate('random_int') u = vg.allocate('random_int') func1 = FunctionOperatorComposition(0.5 * L2NormSquared(b=b), operator) func2 = LeastSquares(operator, b, 0.5) self.assertNumpyArrayAlmostEqual(func1(u), func2(u)) self.assertNumpyArrayAlmostEqual(func1.L, func2.L)
def test_axpby4(self): # test axpby with nested BlockDataContainer ig0 = ImageGeometry(2, 3, 4) ig1 = ImageGeometry(2, 3, 5) data0 = ig0.allocate(-1) data2 = ig0.allocate(1) # data1 = ig0.allocate(2) data3 = ig1.allocate(3) cp0 = BlockDataContainer(data0, data2) cp1 = BlockDataContainer(cp0 * 0. + [2, -2], data3) print(cp1.get_item(0).get_item(0).as_array()) print(cp1.get_item(0).get_item(1).as_array()) print(cp1.get_item(1).as_array()) print("###############################") out = cp1 * 0. cp2 = out + [1, 3] print(cp2.get_item(0).get_item(0).as_array()) print(cp2.get_item(0).get_item(1).as_array()) print(cp2.get_item(1).as_array()) cp2.axpby(3, -2, cp1, out, num_threads=4) # output should be [ [ -1 , 7 ] , 3] res0 = ig0.allocate(-1) res2 = ig0.allocate(7) res3 = ig1.allocate(3) res = BlockDataContainer(BlockDataContainer(res0, res2), res3) # print ("res0", res0.as_array()) # print ("res2", res2.as_array()) print("###############################") # print ("out_0", out.get_item(0).as_array()) # print ("out_1", out.get_item(1).as_array()) self.assertBlockDataContainerEqual(out, res)