Beispiel #1
0
def test_resizing_op_call(odl_tspace_impl):

    impl = odl_tspace_impl
    dtypes = [
        dt for dt in tensor_space_impl(impl).available_dtypes()
        if is_numeric_dtype(dt)
    ]

    for dtype in dtypes:
        # Minimal test since this operator only wraps resize_array
        space = odl.uniform_discr([0, -1], [1, 1], (4, 5), impl=impl)
        res_space = odl.uniform_discr([0, -0.6], [2, 0.2], (8, 2), impl=impl)
        res_op = odl.ResizingOperator(space, res_space)
        out = res_op(space.one())
        true_res = np.zeros((8, 2))
        true_res[:4, :] = 1
        assert np.array_equal(out, true_res)

        out = res_space.element()
        res_op(space.one(), out=out)
        assert np.array_equal(out, true_res)

        # Test also mapping to default impl for other 'impl'
        if impl != 'numpy':
            space = odl.uniform_discr([0, -1], [1, 1], (4, 5), impl=impl)
            res_space = odl.uniform_discr([0, -0.6], [2, 0.2], (8, 2))
            res_op = odl.ResizingOperator(space, res_space)
            out = res_op(space.one())
            true_res = np.zeros((8, 2))
            true_res[:4, :] = 1
            assert np.array_equal(out, true_res)

            out = res_space.element()
            res_op(space.one(), out=out)
            assert np.array_equal(out, true_res)
Beispiel #2
0
def test_resizing_op_mixed_uni_nonuni():
    """Check if resizing along uniform axes in mixed discretizations works."""
    nonuni_part = odl.nonuniform_partition([0, 1, 4])
    uni_part = odl.uniform_partition(-1, 1, 4)
    part = uni_part.append(nonuni_part, uni_part, nonuni_part)
    fspace = odl.FunctionSpace(odl.IntervalProd(part.min_pt, part.max_pt))
    tspace = odl.rn(part.shape)
    space = odl.DiscreteLp(fspace, part, tspace)

    # Keep non-uniform axes fixed
    res_op = odl.ResizingOperator(space, ran_shp=(6, 3, 6, 3))

    assert res_op.axes == (0, 2)
    assert res_op.offset == (1, 0, 1, 0)

    # Evaluation test with a simpler case
    part = uni_part.append(nonuni_part)
    fspace = odl.FunctionSpace(odl.IntervalProd(part.min_pt, part.max_pt))
    tspace = odl.rn(part.shape)
    space = odl.DiscreteLp(fspace, part, tspace)
    res_op = odl.ResizingOperator(space, ran_shp=(6, 3))
    result = res_op(space.one())
    true_result = [[0, 0, 0], [1, 1, 1], [1, 1, 1], [1, 1, 1], [1, 1, 1],
                   [0, 0, 0]]
    assert np.array_equal(result, true_result)

    # Test adjoint
    elem = noise_element(space)
    res_elem = noise_element(res_op.range)
    inner1 = res_op(elem).inner(res_elem)
    inner2 = elem.inner(res_op.adjoint(res_elem))
    assert almost_equal(inner1, inner2)
Beispiel #3
0
    def __init__(self, filter_space, data_space, det_space, w_detv, g_w, a_wc):
        odl.Operator.__init__(self,
                              domain=filter_space,
                              range=data_space,
                              linear=True)

        self.rs_detu = int(2**(np.ceil(np.log2(filter_space.size)) + 1))
        # set =filter.size if filter is twice the detector
        self.frs_detu = self.rs_detu // 2 + 1
        self.rs_filt = odl.ResizingOperator(filter_space,
                                            ran_shp=(self.rs_detu, ))
        self.gw = np.asarray(g_w)
        self.a_wc = a_wc
        self.w_detv = w_detv
        #        self.rs_filt.domain.weighting.const

        self.det_tr_space = odl.uniform_discr(
            [det_space.min_pt[1], det_space.min_pt[0]],
            [det_space.max_pt[1], det_space.max_pt[0]],
            (np.size(det_space, 1), np.size(det_space, 0)))
        self.rs_det = odl.ResizingOperator(self.det_tr_space,
                                           ran_shp=(np.size(self.range,
                                                            2), self.rs_detu))
        self.flt = 'float32'
        self.clx = 'complex64'
        self.flt1 = 'float64'
        self.clx1 = 'complex128'
        thrds = 8
        self.d_a = pyfftw.empty_aligned((np.size(self.range, 2), self.rs_detu),
                                        dtype=self.flt)
        self.d_b = pyfftw.empty_aligned(
            (np.size(self.range, 2), self.frs_detu), dtype=self.clx)
        self.fft_d = pyfftw.FFTW(self.d_a, self.d_b, axes=(1, ), threads=thrds)
        self.id_a = pyfftw.empty_aligned(
            (np.size(self.range, 2), self.frs_detu), dtype=self.clx)
        self.id_b = pyfftw.empty_aligned(
            (np.size(self.range, 2), self.rs_detu), dtype=self.flt)
        self.ifft_d = pyfftw.FFTW(self.id_a,
                                  self.id_b,
                                  axes=(1, ),
                                  threads=thrds,
                                  direction='FFTW_BACKWARD')

        self.f_a = pyfftw.empty_aligned(self.rs_detu, dtype=self.flt)
        self.f_b = pyfftw.empty_aligned(self.frs_detu, dtype=self.clx)
        self.fft_f = pyfftw.FFTW(self.f_a, self.f_b)
        self.if_a = pyfftw.empty_aligned(self.frs_detu, dtype=self.clx1)
        self.if_b = pyfftw.empty_aligned(self.rs_detu, dtype=self.flt1)
        self.ifft_f = pyfftw.FFTW(self.if_a,
                                  self.if_b,
                                  direction='FFTW_BACKWARD')
Beispiel #4
0
def test_resizing_op_adjoint(padding, odl_tspace_impl):

    impl = odl_tspace_impl
    pad_mode, pad_const = padding
    dtypes = [
        dt for dt in tensor_space_impl(impl).available_dtypes()
        if is_real_floating_dtype(dt)
    ]

    for dtype in dtypes:
        space = odl.uniform_discr([0, -1], [1, 1], (4, 5),
                                  dtype=dtype,
                                  impl=impl)
        res_space = odl.uniform_discr([0, -1.4], [1.5, 1.4], (6, 7),
                                      dtype=dtype,
                                      impl=impl)
        res_op = odl.ResizingOperator(space,
                                      res_space,
                                      pad_mode=pad_mode,
                                      pad_const=pad_const)

        if pad_const != 0.0:
            with pytest.raises(NotImplementedError):
                res_op.adjoint
            return

        elem = noise_element(space)
        res_elem = noise_element(res_space)
        inner1 = res_op(elem).inner(res_elem)
        inner2 = elem.inner(res_op.adjoint(res_elem))
        assert almost_equal(inner1, inner2, places=dtype_places(dtype))
Beispiel #5
0
def test_resizing_op_properties(odl_tspace_impl, padding):

    impl = odl_tspace_impl
    dtypes = [
        dt for dt in tensor_space_impl(impl).available_dtypes()
        if is_numeric_dtype(dt)
    ]

    pad_mode, pad_const = padding

    for dtype in dtypes:
        # Explicit range
        space = odl.uniform_discr([0, -1], [1, 1], (10, 5), dtype=dtype)
        res_space = odl.uniform_discr([0, -3], [2, 3], (20, 15), dtype=dtype)
        res_op = odl.ResizingOperator(space,
                                      res_space,
                                      pad_mode=pad_mode,
                                      pad_const=pad_const)

        assert res_op.domain == space
        assert res_op.range == res_space
        assert res_op.offset == (0, 5)
        assert res_op.pad_mode == pad_mode
        assert res_op.pad_const == pad_const
        if pad_mode == 'constant' and pad_const != 0:
            assert not res_op.is_linear
        else:
            assert res_op.is_linear

        # Implicit range via ran_shp and offset
        res_op = odl.ResizingOperator(space,
                                      ran_shp=(20, 15),
                                      offset=[0, 5],
                                      pad_mode=pad_mode,
                                      pad_const=pad_const)
        assert np.allclose(res_op.range.min_pt, res_space.min_pt)
        assert np.allclose(res_op.range.max_pt, res_space.max_pt)
        assert np.allclose(res_op.range.cell_sides, res_space.cell_sides)
        assert res_op.range.dtype == res_space.dtype
        assert res_op.offset == (0, 5)
        assert res_op.pad_mode == pad_mode
        assert res_op.pad_const == pad_const
        if pad_mode == 'constant' and pad_const != 0:
            assert not res_op.is_linear
        else:
            assert res_op.is_linear
Beispiel #6
0
def test_resizing_op_deriv(padding):
    pad_mode, pad_const = padding
    space = odl.uniform_discr([0, -1], [1, 1], (4, 5))
    res_space = odl.uniform_discr([0, -0.6], [2, 0.2], (8, 2))
    res_op = odl.ResizingOperator(space, res_space, pad_mode=pad_mode,
                                  pad_const=pad_const)
    res_op_deriv = res_op.derivative(space.one())

    if pad_mode == 'constant' and pad_const != 0:
        # Only non-trivial case is constant padding with const != 0
        assert res_op_deriv.pad_mode == 'constant'
        assert res_op_deriv.pad_const == 0.0
    else:
        assert res_op_deriv is res_op
Beispiel #7
0
def test_resizing_op_inverse(padding, odl_tspace_impl):

    impl = odl_tspace_impl
    pad_mode, pad_const = padding
    dtypes = [dt for dt in tensor_space_impl(impl).available_dtypes()
              if is_numeric_dtype(dt)]

    for dtype in dtypes:
        space = odl.uniform_discr([0, -1], [1, 1], (4, 5), dtype=dtype,
                                  impl=impl)
        res_space = odl.uniform_discr([0, -1.4], [1.5, 1.4], (6, 7),
                                      dtype=dtype, impl=impl)
        res_op = odl.ResizingOperator(space, res_space, pad_mode=pad_mode,
                                      pad_const=pad_const)

        # Only left inverse if the operator extends in all axes
        x = noise_element(space)
        assert res_op.inverse(res_op(x)) == x
Beispiel #8
0
def test_resizing_op_init(odl_tspace_impl, padding):
    # Test if the different init patterns run
    impl = odl_tspace_impl
    pad_mode, pad_const = padding

    space = odl.uniform_discr([0, -1], [1, 1], (10, 5), impl=impl)
    res_space = odl.uniform_discr([0, -3], [2, 3], (20, 15), impl=impl)

    odl.ResizingOperator(space, res_space)
    odl.ResizingOperator(space, ran_shp=(20, 15))
    odl.ResizingOperator(space, ran_shp=(20, 15), offset=(0, 5))
    odl.ResizingOperator(space, ran_shp=(20, 15), pad_mode=pad_mode)
    odl.ResizingOperator(space, ran_shp=(20, 15), pad_mode=pad_mode,
                         pad_const=pad_const)
    odl.ResizingOperator(space, ran_shp=(20, 15),
                         discr_kwargs={'nodes_on_bdry': True})
Beispiel #9
0
def test_resizing_op_inverse(padding, fn_impl):
    pad_mode, pad_const = padding
    dtypes = [
        dt for dt in odl.FN_IMPLS[fn_impl].available_dtypes()
        if is_scalar_dtype(dt)
    ]

    for dtype in dtypes:
        space = odl.uniform_discr([0, -1], [1, 1], (4, 5),
                                  dtype=dtype,
                                  impl=fn_impl)
        res_space = odl.uniform_discr([0, -1.4], [1.5, 1.4], (6, 7),
                                      dtype=dtype,
                                      impl=fn_impl)
        res_op = odl.ResizingOperator(space,
                                      res_space,
                                      pad_mode=pad_mode,
                                      pad_const=pad_const)

        # Only left inverse if the operator extentds in all axes
        x = noise_element(space)
        assert res_op.inverse(res_op(x)) == x
Beispiel #10
0
def MTF_x(filts, voxels, angles, src_rad, det_rad):
    nVar, step = 6, 2
    MTF_list = np.zeros((len(filts), voxels[0] // 2))
    for k in range(nVar):
        DO = phantom(voxels,
                     'Plane_yz',
                     angles,
                     None,
                     src_rad,
                     det_rad,
                     offset_x=step * k - (nVar // 2) * step)
        CTo = CT.CCB_CT(DO)
        CTo.init_algo()
        CTo.init_DDF_FDK()
        mid = voxels[0] // 2
        pad_op = odl.ResizingOperator(DO.reco_space,
                                      ran_shp=(voxels[0] * 2, voxels[1],
                                               voxels[2]))
        tel = 0
        for f in filts:
            if type(f) == list:
                PlSF_x = CTo.FDK.filt_LP('Shepp-Logan',
                                         f,
                                         compute_results='no')
            elif type(f) == str:
                PlSF_x = CTo.FDK.do(f, compute_results='no')
            else:
                PlSF_x = CTo.FDK_bin(f)

            MTF_x = pad_op.inverse(
                np.abs(
                    np.fft.fftshift(
                        np.fft.fftn(np.fft.ifftshift(pad_op(PlSF_x))))))

            MTF_list[tel] += MTF_x[mid:, mid, mid] / MTF_x[mid, mid,
                                                           mid] / nVar
            tel += 1
    return MTF_list
Beispiel #11
0
def test_resizing_op_raise():

    # domain not a uniformely discretized Lp
    with pytest.raises(TypeError):
        odl.ResizingOperator(odl.rn(5), ran_shp=(10, ))

    grid = odl.RectGrid([0, 2, 3])
    part = odl.RectPartition(odl.IntervalProd(0, 3), grid)
    fspace = odl.FunctionSpace(odl.IntervalProd(0, 3))
    dspace = odl.rn(3)
    space = odl.DiscreteLp(fspace, part, dspace)
    with pytest.raises(ValueError):
        odl.ResizingOperator(space, ran_shp=(10, ))

    # different cell sides in domain and range
    space = odl.uniform_discr(0, 1, 10)
    res_space = odl.uniform_discr(0, 1, 15)
    with pytest.raises(ValueError):
        odl.ResizingOperator(space, res_space)

    # non-integer multiple of cell sides used as shift (grid of the
    # resized space shifted)
    space = odl.uniform_discr(0, 1, 5)
    res_space = odl.uniform_discr(-0.5, 1.5, 10)
    with pytest.raises(ValueError):
        odl.ResizingOperator(space, res_space)

    # need either range or ran_shp
    with pytest.raises(ValueError):
        odl.ResizingOperator(space)

    # offset cannot be combined with range
    space = odl.uniform_discr([0, -1], [1, 1], (10, 5))
    res_space = odl.uniform_discr([0, -3], [2, 3], (20, 15))
    with pytest.raises(ValueError):
        odl.ResizingOperator(space, res_space, offset=(0, 0))

    # bad pad_mode
    with pytest.raises(ValueError):
        odl.ResizingOperator(space, res_space, pad_mode='something')

class TranslationCostFixedTemplNum(TranslationCostFixedTempl):
    @property
    def gradient(self):
        step = 2 * max(self.f.space.cell_sides)
        return odl.solvers.NumericalGradient(self, step=step)


# %% Testing

space = odl.uniform_discr([-1, -1, -1], [1, 1, 1], (150, 150, 150),
                          interp='linear')
templ = odl.phantom.shepp_logan(space, modified=True)
# Make a bit bigger to avoid hitting the boundary
resize = odl.ResizingOperator(space, ran_shp=(256, 256, 256))
templ = resize(templ)
true_t = (0.5, -0.5, 0.5)
templ_shifted = TranslationOperatorFixedTempl(templ)(true_t)
templ.show()
templ_shifted.show()

# Define spaces of different resolutions
space_hires = resize.range
space_midres = odl.uniform_discr(space_hires.min_pt,
                                 space_hires.max_pt,
                                 shape=(128, 128, 128))
space_lowres = odl.uniform_discr(space_hires.min_pt,
                                 space_hires.max_pt,
                                 shape=(32, 32, 32))
Beispiel #13
0
def Create_dataset_ASTRA_real(dataset,
                              pix_size,
                              src_rad,
                              det_rad,
                              ang_freq,
                              Exp_bin,
                              bin_param,
                              vox=None,
                              vecs=None):

    # ! ! ! We overide 'vox' and 'vecs' later on
    # The size of the measured objects in voxels
    data_obj = ddf.real_data(dataset,
                             pix_size,
                             src_rad,
                             det_rad,
                             ang_freq,
                             vox=vox,
                             vecs=vecs)
    g = np.ascontiguousarray(np.transpose(np.asarray(data_obj.g.copy()),
                                          (2, 0, 1)),
                             dtype=np.float32)
    v, ang, u = g.shape
    if vox is None:
        voxels = data_obj.voxels

    else:
        voxels = [vox, vox, vox]

    MaxVoxDataset = np.max([int(voxels[0]**3 * 0.005), 5 * 10**6])

    Smat = Make_Smat(voxels, MaxVoxDataset, '', real_data=dataset['mask'])

    # %% Create geometry
    geom = data_obj.geometry
    w_du = data_obj.pix_size
    dpix = [u, v]

    minvox = data_obj.reco_space.min_pt[0]
    maxvox = data_obj.reco_space.max_pt[0]
    vox = np.shape(data_obj.reco_space)[0]
    vol_geom = astra.create_vol_geom(vox, vox, vox, minvox, maxvox, minvox,
                                     maxvox, minvox, maxvox)

    # Build a vecs vector from the geometry, or load it
    if type(geom) == np.ndarray:
        vecs = geom
        proj_geom = astra.create_proj_geom('cone_vec', v, u, vecs)
    elif type(geom) == odl.tomo.geometry.conebeam.ConeFlatGeometry:
        angles = np.linspace((1 / ang) * np.pi, (2 + 1 / ang) * np.pi, ang,
                             False)
        w_du, w_dv = 2 * data_obj.geometry.detector.partition.max_pt / [u, v]
        proj_geom = astra.create_proj_geom('cone', w_dv, w_du, v, u, angles,
                                           data_obj.geometry.src_radius,
                                           data_obj.geometry.det_radius)

    filter_part = odl.uniform_partition(-data_obj.detecsize[0],
                                        data_obj.detecsize[0], dpix[0])

    filter_space = odl.uniform_discr_frompartition(filter_part,
                                                   dtype='float64')
    spf_space, Exp_op = ddf.ExpOp_builder(bin_param,
                                          filter_space,
                                          interp=Exp_bin)

    nParam = np.size(spf_space)

    fullFilterSize = int(2**(np.ceil(np.log2(dpix[0])) + 1))
    halfFilterSize = fullFilterSize // 2 + 1

    Resize_Op = odl.ResizingOperator(Exp_op.range, ran_shp=(fullFilterSize, ))
    # %% Create projection and reconstion objects
    proj_id = astra.data3d.link('-proj3d', proj_geom, g)

    rec = np.zeros(astra.geom_size(vol_geom), dtype=np.float32)
    rec_id = astra.data3d.link('-vol', vol_geom, rec)

    B = np.zeros((MaxVoxDataset, nParam + 1))

    # %% Make the matrix columns of the matrix B
    for nP in range(nParam):
        unit_vec = spf_space.zero()
        unit_vec[nP] = 1
        filt = Exp_op(unit_vec)

        rs_filt = Resize_Op(filt)

        f_filt = np.real(np.fft.rfft(np.fft.ifftshift(rs_filt)))
        filter2d = np.zeros((ang, halfFilterSize))
        for i in range(ang):
            filter2d[i, :] = f_filt * 4 * w_du

        # %% Make a filter geometry
        filter_geom = astra.create_proj_geom('parallel', w_du, halfFilterSize,
                                             np.zeros(ang))
        filter_id = astra.data2d.create('-sino', filter_geom, filter2d)
        #

        cfg = astra.astra_dict('FDK_CUDA')
        cfg['ReconstructionDataId'] = rec_id
        cfg['ProjectionDataId'] = proj_id
        cfg['option'] = {'FilterSinogramId': filter_id}
        # Create the algorithm object from the configuration structure
        alg_id = astra.algorithm.create(cfg)

        # %%
        astra.algorithm.run(alg_id)
        rec = np.transpose(rec, (2, 1, 0))
        B[:, nP] = rec[Smat]
    # %%
    # Clean up. Note that GPU memory is tied up in the algorithm object,
    # and main RAM in the data objects.
    B[:, -1] = data_obj.f[Smat]
    astra.algorithm.delete(alg_id)
    astra.data3d.delete(rec_id)
    astra.data3d.delete(proj_id)
    return B
def NNFDK_astra(g,
                NW,
                geom,
                reco_space,
                w_du,
                Exp_op,
                node_output,
                ang_freq=None):
    # %% Create geometry
    # Make a circular scanning geometry
    ang, u, v = g.shape
    minvox = reco_space.min_pt[0]
    maxvox = reco_space.max_pt[0]
    vox = np.shape(reco_space)[0]
    vol_geom = astra.create_vol_geom(vox, vox, vox, minvox, maxvox, minvox,
                                     maxvox, minvox, maxvox)

    if type(geom) == np.ndarray:
        vecs = geom
        proj_geom = astra.create_proj_geom('cone_vec', v, u, vecs)
    elif type(geom) == odl.tomo.geometry.conebeam.ConeFlatGeometry:
        angles = np.linspace((1 / ang) * np.pi, (2 + 1 / ang) * np.pi, ang,
                             False)
        w_du, w_dv = 2 * geom.detector.partition.max_pt / [u, v]
        proj_geom = astra.create_proj_geom('cone', w_dv, w_du, v, u, angles,
                                           geom.src_radius, geom.det_radius)

    g = np.transpose(np.asarray(g), (2, 0, 1))
    # %%
    proj_id = astra.data3d.create('-proj3d', proj_geom, g)
    rec = np.zeros(astra.geom_size(vol_geom), dtype=np.float32)

    rec_tot = np.zeros(astra.geom_size(vol_geom), dtype=np.float32)

    rec_id = astra.data3d.link('-vol', vol_geom, rec)

    fullFilterSize = int(2**(np.ceil(np.log2(u)) + 1))
    halfFilterSize = fullFilterSize // 2 + 1
    filter2d = np.zeros((ang, halfFilterSize))
    Resize_Op = odl.ResizingOperator(Exp_op.range, ran_shp=(fullFilterSize, ))
    # %% Make a filter geometry

    filter_geom = astra.create_proj_geom('parallel', w_du, halfFilterSize,
                                         np.zeros(ang))

    cfg = astra.astra_dict('FDK_CUDA')
    cfg['ReconstructionDataId'] = rec_id
    cfg['ProjectionDataId'] = proj_id

    # Create the algorithm object from the configuration structure
    # %%
    # Set a container list for the learned filters
    h_e = []
    if node_output:
        mid = v // 2
        node_output_axis = []

    for i in range(NW['nNodes']):
        h = NW['l1'][:-1, i] * 2 * NW['sc1'][0, :]
        h_e += [h]
        b = NW['l1'][-1, i] + np.sum(
            NW['l1'][:-1, i]) + 2 * np.dot(NW['l1'][:-1, i], NW['sc1'][1, :])
        filter2d = Exp_op_FFT(Exp_op, h, filter2d, Resize_Op, w_du)

        filter_id = astra.data2d.create('-sino', filter_geom, filter2d)
        cfg['option'] = {'FilterSinogramId': filter_id}
        alg_id = astra.algorithm.create(cfg)
        astra.algorithm.run(alg_id)
        rec_tot = hidden_layer(rec, rec_tot, NW['l2'][i], b)
        if node_output:
            rec2 = hidden_layer(rec, 0, NW['l2'][i], b)
            node_output_axis += [
                rec2[:, :, mid], rec2[:, mid, :], rec2[mid, :, :]
            ]

    # Make a numpy array of the filter list
    h_e = np.asarray(h_e)
    # b_o = self.network['l2'][-1]
    rec_tot = outer_layer(rec_tot, NW['l2'][-1], NW['sc2'][0], NW['sc2'][1])
    rec_tot = np.transpose(rec_tot, (2, 1, 0))

    # %% Make the matrix columns of the matrix B

    # %%
    # Clean up. Note that GPU memory is tied up in the algorithm object,
    # and main RAM in the data objects.
    astra.algorithm.delete(alg_id)
    astra.data3d.delete(rec_id)
    astra.data3d.delete(proj_id)
    if node_output:
        return rec_tot, h_e, node_output_axis
    else:
        return rec_tot, h_e
Beispiel #15
0
def Create_dataset_ASTRA_sim(pix, phantom, angles, src_rad, noise, Exp_bin,
                             bin_param, **kwargs):
    if phantom == 'Defrise':
        phantom = 'Defrise random'
    if phantom == 'Fourshape_test':
        phantom = 'Fourshape'

    if 'MaxVoxDataset' in kwargs:
        MaxVoxDataset = kwargs['MaxVoxDataset']

    else:
        MaxVoxDataset = np.max([int(pix**3 * 0.005), 1 * 10**6])

    # The size of the measured objects in voxels
    voxels = [pix, pix, pix]
    dpix = [voxels[0] * 2, voxels[1]]
    u, v = dpix
    # ! ! ! This will lead to some problems later on ! ! !
    det_rad = 0
    data_obj = ddf.phantom(voxels,
                           phantom,
                           angles,
                           noise,
                           src_rad,
                           det_rad,
                           compute_xHQ=True)
    WV_obj = ddf.support_functions.working_var_map()
    WV_path = WV_obj.WV_path
    data_obj.make_mask(WV_path)
    Smat = Make_Smat(voxels, MaxVoxDataset, WV_path)
    # %% saving tiffs for CNNs
    w_du = data_obj.w_detu
    filt = make_hann_filt(voxels, w_du)
    xFDK = ddf.FDK_ODL_astra_backend.FDK_astra(data_obj.g, filt,
                                               data_obj.geometry,
                                               data_obj.reco_space, None)

    # %% Create geometry
    # Make a circular scanning geometry
    minvox = data_obj.reco_space.min_pt[0]
    maxvox = data_obj.reco_space.max_pt[0]
    vox = np.shape(data_obj.reco_space)[0]
    vol_geom = astra.create_vol_geom(vox, vox, vox, minvox, maxvox, minvox,
                                     maxvox, minvox, maxvox)

    ang = np.linspace((1 / angles) * np.pi, (2 + 1 / angles) * np.pi, angles,
                      False)
    w_du, w_dv = 2 * data_obj.geometry.detector.partition.max_pt / [u, v]
    proj_geom = astra.create_proj_geom('cone', w_dv, w_du, v, u, ang,
                                       data_obj.geometry.src_radius,
                                       data_obj.geometry.det_radius)
    filter_part = odl.uniform_partition(-data_obj.detecsize[0],
                                        data_obj.detecsize[0], u)

    filter_space = odl.uniform_discr_frompartition(filter_part,
                                                   dtype='float64')
    spf_space, Exp_op = ddf.support_functions.ExpOp_builder(bin_param,
                                                            filter_space,
                                                            interp=Exp_bin)
    nParam = np.size(spf_space)

    fullFilterSize = int(2**(np.ceil(np.log2(dpix[0])) + 1))
    halfFilterSize = fullFilterSize // 2 + 1

    Resize_Op = odl.ResizingOperator(Exp_op.range, ran_shp=(fullFilterSize, ))
    # %% Create forward and backward projector
    #    project_id = astra.create_projector('cuda3d', proj_geom, vol_geom)
    #    W = astra.OpTomo(project_id)

    # %% Create data
    proj_data = np.transpose(np.asarray(data_obj.g), (2, 0, 1)).copy()
    #    W.FP(np.transpose(np.asarray(data_obj.f), (2, 1, 0)))

    # ! ! ! wat is deze? ! ! !
    # if noise is not None:
    #     g = add_poisson_noise(proj_data, noise[1])
    # else:
    g = proj_data

    proj_id = astra.data3d.link('-sino', proj_geom, g)

    rec = np.zeros(astra.geom_size(vol_geom), dtype=np.float32)
    rec_id = astra.data3d.link('-vol', vol_geom, rec)

    B = np.zeros((MaxVoxDataset, nParam + 1))

    # %% Make the matrix columns of the matrix B
    for nP in range(nParam):
        unit_vec = spf_space.zero()
        unit_vec[nP] = 1
        filt = Exp_op(unit_vec)

        rs_filt = Resize_Op(filt)

        f_filt = np.real(np.fft.rfft(np.fft.ifftshift(rs_filt)))
        filter2d = np.zeros((angles, halfFilterSize))
        for i in range(angles):
            filter2d[i, :] = f_filt * 4 * w_du

        # %% Make a filter geometry
        filter_geom = astra.create_proj_geom('parallel', w_du, halfFilterSize,
                                             np.zeros((angles)))

        filter_id = astra.data2d.create('-sino', filter_geom, filter2d)
        #

        cfg = astra.astra_dict('FDK_CUDA')
        cfg['ReconstructionDataId'] = rec_id
        cfg['ProjectionDataId'] = proj_id
        cfg['option'] = {'FilterSinogramId': filter_id}
        # Create the algorithm object from the configuration structure
        alg_id = astra.algorithm.create(cfg)

        # %%
        astra.algorithm.run(alg_id)
        rec = np.transpose(rec, (2, 1, 0))
        B[:, nP] = rec[Smat]
    # %%
    # Clean up. Note that GPU memory is tied up in the algorithm object,
    # and main RAM in the data objects.
    B[:, -1] = data_obj.xHQ[Smat]
    #    B[:, -1] = data_obj.f[Smat]
    astra.algorithm.delete(alg_id)
    astra.data3d.delete(rec_id)
    astra.data3d.delete(proj_id)
    return B, data_obj.xHQ, xFDK
Beispiel #16
0
                                           impl='astra_cuda')

    # Phantom
    phantom_c = odl.phantom.shepp_logan(coarse_discr, modified=True)
    phantom_f = odl.phantom.shepp_logan(fine_discr, modified=True)

    # Define insert discretization using the fine cell sizes but the insert
    # min and max points
    insert_discr = odl.uniform_discr_fromdiscr(
        fine_discr,
        min_pt=insert_min_pt,
        max_pt=insert_max_pt,
        cell_sides=fine_discr.cell_sides)

    # Restrict the phantom to the insert discr
    resizing_operator = odl.ResizingOperator(fine_discr, insert_discr)
    phantom_insert = resizing_operator(phantom_f)

    # Ray trafo on the insert discretization only
    insert_ray_trafo = odl.tomo.RayTransform(insert_discr,
                                             geometry,
                                             impl='astra_cuda')

    # Forward operator = sum of masked coarse ray trafo and insert ray trafo
    sum_ray_trafo = odl.ReductionOperator(masked_coarse_ray_trafo,
                                          insert_ray_trafo)

    # Make phantom in the product space
    pspace = sum_ray_trafo.domain
    phantom = pspace.element([phantom_c, phantom_insert])
    multigrid.graphics.show_both(*phantom)
Beispiel #17
0
# Calculate the FT only along the first axis.
ft_op_axis0 = odl.trafos.FourierTransform(space, axes=0)
phantom_ft_axis0 = ft_op_axis0(phantom)
phantom_ft_axis0.show(title='Fourier transform along axis 0')

# If a real space is used, the Fourier transform can be calculated in the
# "half-complex" mode. This means that along the last axis of the transform,
# only the negative half of the spectrum is stored since the other half is
# its complex conjugate. This is faster and more memory efficient.
real_space = space.real_space
ft_op_halfc = odl.trafos.FourierTransform(real_space, halfcomplex=True)
phantom_real = odl.phantom.shepp_logan(real_space, modified=True)
phantom_real.show(title='Shepp-Logan phantom, real version')
phantom_real_ft = ft_op_halfc(phantom_real)
phantom_real_ft.show(title='Half-complex Fourier Transform')

# If the space is real, the inverse also gives a real result.
phantom_real_ft_inv = ft_op_halfc.inverse(phantom_real_ft)
phantom_real_ft_inv.show(title='Half-complex Fourier Transform inverted',
                         force_show=True)

# The FT operator itself has no option of (zero-)padding, but it can be
# composed with a `ResizingOperator` which does exactly that. Note that the
# FT needs to be redefined on the enlarged space.
padding_op = odl.ResizingOperator(space, ran_shp=(768, 768))
ft_op = odl.trafos.FourierTransform(padding_op.range)
padded_ft_op = ft_op * padding_op
phantom_ft_padded = padded_ft_op(phantom)
phantom_ft_padded.show('Padded FT of the phantom')
Beispiel #18
0
    angle = x[0]
    det_var = x[1]
    return np.sin(angle) * det_var


def deriv1_ft(x):
    angle = x[0]
    det_var = x[1]
    return -np.cos(angle) * det_var


# Fourier transform on the range of the FT along the detector axis, including
# padding
ran_shp = (ray_trafo.range.shape[0],
           ray_trafo.range.shape[1] * 2 - 1)
resizing = odl.ResizingOperator(ray_trafo.range, ran_shp=ran_shp,
                                pad_mode='order0')

fourier = odl.trafos.FourierTransform(resizing.range, axes=1, impl='pyfftw')
fourier = fourier * resizing

# Ramp filter part
alen = ray_trafo.geometry.motion_params.length
ramp_filter = 1 / (2 * alen) * fourier.range.element(lambda x: abs(x[1]))

# Smoothing filter (mollifier) for the reconstruction kernel (Fourier space)
gaussian_ker = fourier.domain.element(gaussian_det, s=0.15)
exp_filter = fourier(gaussian_ker)

# Filters for lambda reconstruction
lambda_filter_ft = fourier.range.element(lambda_ft)
lambda_kernel_ft = exp_filter * ramp_filter * lambda_filter_ft