예제 #1
0
파일: process.py 프로젝트: cicwi/flexCALC
def _modifier_l2cost_(projections,
                      geometry,
                      subsample,
                      value,
                      key,
                      metric='gradient',
                      preview=False):
    '''
    Cost function based on L2 norm of the first derivative of the volume. Computation of the first derivative is done by FDK with pre-initialized reconstruction filter.
    '''
    geometry_ = geometry.copy()

    geometry_[key] = value

    vol = _sample_FDK_(projections, geometry_, subsample)

    vol[vol < 0] = 0

    # Crop to central part:
    sz = numpy.array(vol.shape) // 8 + 1
    if vol.shape[0] < 3:
        vol = vol[:, sz[1]:-sz[1], sz[2]:-sz[2]]
    else:
        vol = vol[sz[0]:-sz[0], sz[1]:-sz[1], sz[2]:-sz[2]]

    #vol /= vol.max()

    l2 = 0

    for ii in range(vol.shape[0]):
        if metric == 'gradient':
            grad = numpy.gradient(numpy.squeeze(vol[ii, :, :]))
            grad = (grad[0]**2 + grad[1]**2)

            l2 += numpy.mean(grad[grad > 0])

        elif metric == 'highpass':

            l2 += numpy.mean(
                (ndimage.gaussian_filter(vol[ii, :, :], 2) - vol[ii, :, :])**2)

        elif metric == 'correlation':

            im = vol[ii, :, :]
            im = numpy.pad(im, ((im.shape[0], 0), (im.shape[1], 0)),
                           mode='constant')
            im = numpy.fft.fft2(im)
            im = numpy.abs(numpy.fft.ifft2(im * numpy.conj(im)))
            #l2 += im[0,0]
            l2 += numpy.abs(numpy.mean(im * numpy.conj(im)))

        else:
            raise Exception('Unknown metric: ' + metric)

    if preview:
        display.slice(vol, title='Guess = %0.2e, L2 = %0.2e' % (value, l2))

    return -l2
예제 #2
0
def FISTA( projections, volume, geometry, iterations, lmbda = 0):
    '''
    FISTA reconstruction. Right now there is no TV minimization substep here!
    '''
    ss = settings
    preview = ss.preview    
    bounds = ss.bounds
        
    # Residual norms:    
    rnorms = []
    
    # Various variables:
    t = 1
    volume_t = volume.copy()
    volume_old = volume.copy()
    
    # TV residual:
    sz = list(volume.shape)
    sz.insert(0, 3)
    volume_tv = numpy.zeros(sz, dtype = 'float32')
    
    logger.print('FISTING started...')
    
    # Progress bar:
    pbar = _pbar_start_(iterations, 'iterations')
    
    for ii in range(iterations):
        
        # L2 update:
        norm = fista_update(projections, volume, volume_old, volume_t, volume_tv, t, geometry, lmbda = lmbda)
        
        if norm:
            rnorms.append(norm)
        
        # Apply bounds:
        if bounds:
            numpy.clip(volume, a_min = bounds[0], a_max = bounds[1], out = volume)    
         
        # Show preview or progress:    
        if preview:
            display.slice(volume, dim = 1, title = 'Preview')
        else:
            _pbar_update_(pbar)

    # Stop progress bar    
    _pbar_close_(pbar)
            
    if rnorms:   
         display.plot(rnorms, semilogy = True, title = 'Resudual norm')
예제 #3
0
def EM( projections, volume, geometry, iterations):
    """
    Expectation Maximization
    """ 
    ss = settings
    preview = ss.preview    
    bounds = ss.bounds
    
    # Make sure that the volume is positive:
    if (volume.max() == 0)|(volume.min()<0): 
        logger.error('Wrong initial guess. Make sure that initial guess for EM is positive.')
    
    if (projections.min() < 0):    
        logger.error('Wrong projection data. Make sure that projections have no negative values.')
    
    logger.print('Em Emm Emmmm...')
    
    # Residual norms:    
    rnorms = []
    
    # Progress bar:
    pbar = _pbar_start_(iterations, 'iterations')
        
    for ii in range(iterations):
        
        # Update volume:
        norm = em_update(projections, volume, geometry)
        
        # Apply bounds
        if bounds:
            numpy.clip(volume, a_min = bounds[0], a_max = bounds[1], out = volume) 
                               
        if norm:
            rnorms.append(norm)
            
        if preview:
            display.slice(volume, dim = 1, title = 'Preview')
        else:
            _pbar_update_(pbar)

    # Stop progress bar    
    _pbar_close_(pbar)
            
    if rnorms:   
         display.plot(rnorms, semilogy = True, title = 'Resudual norm') 
예제 #4
0
파일: process.py 프로젝트: cicwi/flexCALC
def register_astra_geometry(proj_fix, proj_mov, geom_fix, geom_mov, subsamp=1):
    """
    Compute a rigid transformation that makes sure that two reconstruction volumes are alligned.
    Args:
        proj_fix : projection data of the fixed volume
        proj_mov : projection data of the fixed volume
        geom_fix : projection data of the fixed volume
        geom_mov : projection data of the fixed volume
        
    Returns:
        geom : geometry for the second reconstruction volume
    """

    print('Computing a rigid tranformation between two datasets.')

    # Find maximum vol size:
    sz = numpy.array([proj_fix.shape, proj_mov.shape]).max(0)
    sz += 10  # for safety...

    vol1 = numpy.zeros(sz, dtype='float32')
    vol2 = numpy.zeros(sz, dtype='float32')

    projector.settings.bounds = [0, 10]
    projector.settings.subsets = 10
    projector.settings['mode'] = 'sequential'

    projector.FDK(proj_fix, vol1, geom_fix)
    projector.SIRT(proj_fix, vol1, geom_fix, iterations=5)

    projector.FDK(proj_mov, vol2, geom_mov)
    projector.SIRT(proj_mov, vol2, geom_mov, iterations=5)

    display.slice(vol1, title='Fixed volume preview')
    display.slice(vol1, title='Moving volume preview')

    # Find transformation between two volumes:
    R, T = register_volumes(vol1,
                            vol2,
                            subsamp=subsamp,
                            use_moments=True,
                            use_CG=True)

    return R, T
예제 #5
0
def PWLS(projections, volume, geometry, iterations):
    """
    Simple implementation of the Penalized Weighted Least Squeares. 
    Gives better results when photon starvation and metal artifacts are present in small parts of the volume.
    Needs more memory than SIRT!
    """ 
    ss = settings
    preview = ss.preview    
    bounds = ss.bounds
    
    logger.print('PWLS-PWLS-PWLS-PWLS...')
    
    # Residual norms:    
    rnorms = []
    
    # Progress bar:
    pbar = _pbar_start_(iterations, 'iterations')
        
    for ii in range(iterations):
        
        # L2 update:
        norm = pwls_update(projections, volume, geometry)
        
        if norm:
            rnorms.append(norm)
        
        # Apply bounds
        if bounds:
            numpy.clip(volume, a_min = bounds[0], a_max = bounds[1], out = volume)    
       
        if preview:
            display.slice(volume, dim = 1, title = 'Preview')
        else:
            _pbar_update_(pbar)

    # Stop progress bar    
    _pbar_close_(pbar)
                     
    if rnorms:   
         display.plot(rnorms, semilogy = True, title = 'Resudual L2') 
예제 #6
0
파일: process.py 프로젝트: cicwi/flexCALC
def append_volume(array, geom, tot_array, tot_geom, ramp=10):
    """
    Append a volume array to a larger arrayset.
    Args:
        
        array: projection stack
        geom: geometry descritption
        tot_array: output array
        tot_geom: output geometry
        
    """
    print('Stitching a volume block...')

    display.slice(array, dim=2, title='Append')
    display.slice(tot_array, dim=2, title='Total')

    # Offset (pixel precision):
    offset = numpy.array(geom['vol_tra']) / geom['img_pixel'] - numpy.array(
        array.shape) / 2
    offset -= numpy.array(
        tot_geom['vol_tra']) / tot_geom['img_pixel'] - numpy.array(
            tot_array.shape) / 2
    offset = numpy.round(offset).astype('int')

    # Create a slice of the big arrayset:
    s0 = slice(offset[0], offset[0] + array.shape[0])
    s1 = slice(offset[1], offset[1] + array.shape[1])
    s2 = slice(offset[2], offset[2] + array.shape[2])

    # Writable view on the total array:
    w_array = tot_array[s0, s1, s2]

    # Find shift:
    shift = find_shift(w_array, array)

    print('Found shift of :' + str(shift))

    if numpy.abs(shift).max() > 0: array = translate(array, -shift, order=1)
    print('Computing weigths.')
    # Ramp weight:
    weight = numpy.ones(array.shape, dtype='float16')
    weight = data.ramp(weight, 0, [ramp, ramp], mode='linear')
    weight = data.ramp(weight, 1, [ramp, ramp], mode='linear')
    weight = data.ramp(weight, 2, [ramp, ramp], mode='linear')

    # Weight can be 100% where no prior array exists:
    for ii in range(weight.shape[0]):
        weight[ii][w_array[ii] == 0] = 1
    print('Adding volumes.')
    # Apply weights and add (save memory):
    array *= weight

    weight -= 1
    weight *= -1

    w_array *= weight
    w_array += array

    display.slice(tot_array, dim=2, title='Total')
예제 #7
0
def SIRT( projections, volume, geometry, iterations):
    """
    Simultaneous Iterative Reconstruction Technique.
    """ 
    ss = settings
    preview = ss.preview    
    bounds = ss.bounds
    
    logger.print('Feeling SIRTy...')
    
    # Residual norms:    
    rnorms = []
    
    # Progress bar:
    pbar = _pbar_start_(iterations, 'iterations')
        
    for ii in range(iterations):
        
        # L2 update:
        norm = l2_update(projections, volume, geometry)
        
        if norm:
            rnorms.append(norm)
        
        # Apply bounds
        if bounds:
            numpy.clip(volume, a_min = bounds[0], a_max = bounds[1], out = volume)    
       
        if preview:
            display.slice(volume, dim = 1, title = 'Preview')
        else:
            _pbar_update_(pbar)

    # Stop progress bar    
    _pbar_close_(pbar)
                     
    if rnorms:   
         display.plot2d(rnorms, semilogy = True, title = 'Resudual L2')   
예제 #8
0
binning = 2

dark = data.read_stack(path, 'di00', sample = binning)
flat = data.read_stack(path, 'io00', sample = binning)    
proj = data.read_stack(path, 'scan_', skip = binning, sample = binning)

geom = data.read_flexraylog(path, sample = binning)   

#%% Prepro:

flat = (flat - dark).mean(1)
proj = (proj - dark) / flat[:, None, :]
proj = -numpy.log(proj).astype('float32')
proj = numpy.ascontiguousarray(proj)

display.slice(proj, dim = 1, title = 'Projection', cmap = 'magma')

#%% Astra reconstruction:

vol = numpy.zeros([2000 // binning, 2000 // binning, 2000 // binning], dtype = 'float32')

# Initialize ASTRA geometries:
vol_geom = geom.astra_volume_geom(vol.shape)
proj_geom = geom.astra_projection_geom(proj.shape)
        
# This is ASTRAAA!!!
sin_id = astra.data3d.link('-sino', proj_geom, proj)
vol_id = astra.data3d.link('-vol', vol_geom, vol)

cfg = astra.astra_dict('FDK_CUDA')
cfg['ReconstructionDataId'] = vol_id
예제 #9
0
from flextomo import projector
from flextomo import phantom

import numpy

#%% Create volume and forward project (32 projections):
    
# Initialize images:    
proj = numpy.zeros([30, 64, 256], dtype = 'float32')

# Define a simple projection geometry:
geom = geometry.circular(src2obj = 100, det2obj = 100, det_pixel = 0.01, ang_range = [0, 360])

# Create phantom and project into proj:
vol = phantom.abstract_nudes([30, 256, 256], geom, complexity = 8)
display.slice(vol, title = 'Phantom')

# Forward project:
projector.forwardproject(proj, vol, geom)
display.slice(proj, title = 'Sinogram')

#%% Unfiltered back-project

# Make volume:
vol_rec = numpy.zeros_like(vol)

# Backproject:
projector.backproject(proj, vol_rec, geom)
display.slice(vol_rec, title = 'Backprojection')

#%% Filtered back-project
예제 #10
0
# Define a simple projection geometry:
geom_a = geometry.circular(src2obj=100,
                           det2obj=100,
                           det_pixel=0.1,
                           ang_range=[0, 360])

# The saceon dataset willl be rotated and translated:
geom_b = geom_a.copy()
geom_b.parameters['vol_rot'] = [0.0, 0.0, 90.0]
geom_b.parameters['vol_tra'] = [0, -0.5, 0]

# Create a phantom:
vol = phantom.random_spheroids([100, 100, 100], geom_a, 10)

display.slice(vol, dim=1, title='Phantom')

#%% Forward model:

# Initialize images:
proj_a = numpy.zeros([128, 32, 128], dtype='float32')
proj_b = numpy.zeros([128, 32, 128], dtype='float32')

# Forward project:
projector.forwardproject(proj_a, vol, geom_a)
projector.forwardproject(proj_b, vol, geom_b)

display.slice(proj_a, dim=1, title='Proj A')
display.slice(proj_b, dim=1, title='Proj B')

#%% Preview reconstructions:
예제 #11
0
#%% Imports

from flexdata import data
from flexdata import display

#%% Read image stacks:

# Read files with 'scan_' in them (sampling = 4 for speed):
path = '/ufs/ciacc/flexbox/skull/'
proj = data.read_stack(path, 'scan_', skip=4, sample=4)

# Writing stack:
data.write_stack(path + 'binned', 'scan_', proj, dim=1)

# Display:
display.slice(proj, dim=0, title='Sinogram', cmap='magma')
display.slice(proj, dim=1, title='Projection', cmap='magma')

#%% Read / write a geometry file:

# Parcer for a flexray log file:
geom = data.read_flexraylog(path, sample=4)

print('\nParsing "scan settings.txt":')
print(geom)

# Write TOML format to disk:
data.write_toml(path + 'geometry.toml', geom)

print('\nReading raw TOML:')
print(data.read_toml(path + 'geometry.toml'))
예제 #12
0
#%% Simulate data with shifted rotation axis

# Initialize images:
proj = numpy.zeros([1, 128, 128], dtype='float32')

# Define a simple projection geometry:
geom = geometry.circular(src2obj=100,
                         det2obj=100,
                         det_pixel=0.1,
                         ang_range=[0, 360])
geom['axs_tan'] = -0.123

# Create phantom and project into proj:
vol = phantom.abstract_nudes([1, 128, 128], geom, 6)
display.slice(vol, title='Phantom')

# Forward project:
projector.forwardproject(proj, vol, geom)
display.slice(proj, title='Sinogram')

#%% Use optimize_rotation_center:

# Unmodified geometry:
geom = geometry.circular(src2obj=100,
                         det2obj=100,
                         det_pixel=0.1,
                         ang_range=[0, 360])

# Optimization:
process.optimize_rotation_center(proj, geom, subscale=2)
예제 #13
0
scratch_path = './scratch.mem'

dark = data.read_stack(path, 'di00', sample=1)
flat = data.read_stack(path, 'io00', sample=1)
proj = data.read_stack(path,
                       'scan_',
                       sample=1,
                       skip=1,
                       dtype='float32',
                       memmap=scratch_path)

geom = data.read_flexraylog(path, sample=1)

#%% Prepro (use implicit operations):

proj -= dark
proj /= (flat - dark).mean(1)[:, None, :]
numpy.log(proj, out=proj)
proj *= -1

display.slice(proj, title='Sinogram. What else?')

#%% FDK Recon:

vol = projector.init_volume(proj)

# Split data into 10 subsets to save memory:
projector.settings.subsets = 10
projector.FDK(proj, vol, geom)

display.slice(vol, bounds=[], title='FDK')
예제 #14
0
#%% Simulate data with shifted rotation axis

# Initialize images:
proj = numpy.zeros([128, 128, 128], dtype='float32')

# Define a simple projection geometry:
geom = geometry.circular(src2obj=100,
                         det2obj=100,
                         det_pixel=0.1,
                         ang_range=[0, 360])
geom['det_roll'] = 1.45

# Create phantom and project into proj:
#vol = phantom.random_spheroids([128, 128, 128], geom, 8)
vol = phantom.cuboid([128, 128, 128], geom, 3, 3, 3)
display.slice(vol, title='Phantom')

# Forward project:
projector.forwardproject(proj, vol, geom)
display.slice(proj, dim=1, title='Projection')

#%% Use optimize_rotation_center:

# Unmodified geometry:
geom = geometry.circular(src2obj=100,
                         det2obj=100,
                         det_pixel=0.1,
                         ang_range=[0, 360])

vol = projector.init_volume(proj)
projector.FDK(proj, vol, geom)
예제 #15
0
path = '/ufs/ciacc/flexbox/good/'

binn = 1
dark = data.read_stack(path, 'di00', sample=binn)
flat = data.read_stack(path, 'io00', sample=binn)
proj = data.read_stack(path, 'scan_', sample=binn, skip=binn)

geom = data.read_flexraylog(path, sample=binn)

#%% Prepro:

flat = (flat - dark).mean(1)
proj = (proj - dark) / flat[:, None, :]
proj = -numpy.log(proj).astype('float32')

display.slice(proj, dim=1, title='Projection')

#%% FDK Recon

vol = projector.init_volume(proj)
projector.FDK(proj, vol, geom)

display.slice(vol, bounds=[], title='FDK')

#%% SIRT with additional options

vol = projector.init_volume(proj)

projector.settings.bounds = [0, 10]
projector.settings.subsets = 10
projector.settings.sorting = 'equidistant'
예제 #16
0
def calibrate_spectrum(projections,
                       volume,
                       geometry,
                       compound='Al',
                       density=2.7,
                       threshold=None,
                       iterations=1000,
                       n_bin=10):
    '''
    Use the projection stack of a homogeneous object to estimate system's 
    effective spectrum.
    Can be used by process.equivalent_thickness to produce an equivalent 
    thickness projection stack.
    Please, use conventional geometry. 
    '''

    #import random

    # Find the shape of the object:
    if threshold:
        t = binary_threshold(volume, mode='constant', threshold=threshold)

        segmentation = numpy.float32()
    else:
        t = binary_threshold(volume, mode='otsu')
        segmentation = numpy.float32(volume > t)

    display.slice(segmentation, dim=0, title='Segmentation')

    # Crop:
    #height = segmentation.shape[0]
    #w = 15

    #length = length[height//2-w:height//2 + w, : ,:]

    # Forward project the shape:
    print('Calculating the attenuation length.')

    length = numpy.zeros_like(projections)
    length = numpy.ascontiguousarray(length)
    projector.forwardproject(length, segmentation, geometry)

    projections[projections < 0] = 0
    intensity = numpy.exp(-projections)

    # Crop to avoid cone artefacts:
    height = intensity.shape[0] // 2
    window = 10
    intensity = intensity[height - window:height + window, :, :]
    length = length[height - window:height + window, :, :]

    # Make 1D:
    intensity = intensity[length > 0].ravel()
    length = length[length > 0].ravel()

    lmax = length.max()
    lmin = length.min()

    print('Maximum reprojected length:', lmax)
    print('Minimum reprojected length:', lmin)

    print('Selecting a random subset of points.')

    # Rare the sample to avoid slow times:
    #index = random.sample(range(length.size), 1000000)
    #length = length[index]
    #intensity = intensity[index]

    print('Computing the intensity-length transfer function.')

    # Bin number for lengthes:
    bin_n = 128
    bins = numpy.linspace(lmin, lmax, bin_n)

    # Sample the midslice:
    #segmentation = segmentation[height//2-w:height//2 + w, : ,:]
    #projections_ = projections[height//2-w:height//2 + w, : ,:]

    #import flexModel
    #ctf = flexModel.get_ctf(length.shape[::2], 'gaussian', [1, 1])
    #length = flexModel.apply_ctf(length, ctf)

    # TODO: Some cropping might be needed to avoid artefacts at the edges

    #flexUtil.slice(length, title = 'length sinogram')
    #flexUtil.slice(projections_, title = 'apparent sinogram')

    # Rebin:
    idx = numpy.digitize(length, bins)

    # Rebin length and intensity:
    length_0 = bins + (bins[1] - bins[0]) / 2
    intensity_0 = [numpy.median(intensity[idx == k]) for k in range(bin_n)]

    # In case some bins are empty:
    intensity_0 = numpy.array(intensity_0)
    length_0 = numpy.array(length_0)
    length_0 = length_0[numpy.isfinite(intensity_0)]
    intensity_0 = intensity_0[numpy.isfinite(intensity_0)]

    # Get rid of tales:
    rim = len(length_0) // 20
    length_0 = length_0[rim:-rim]
    intensity_0 = intensity_0[rim:-rim]

    # Dn't trust low counts!
    length_0 = length_0[intensity_0 > 0.05]
    intensity_0 = intensity_0[intensity_0 > 0.05]

    # Get rid of long rays (they are typically wrong...)
    #intensity_0 = intensity_0[length_0 < 35]
    #length_0 = length_0[length_0 < 35]

    # Enforce zero-one values:
    length_0 = numpy.insert(length_0, 0, 0)
    intensity_0 = numpy.insert(intensity_0, 0, 1)

    #flexUtil.plot(length_0, intensity_0, title = 'Length v.s. Intensity')

    print('Intensity-length curve rebinned.')

    print('Computing the spectrum by Expectation Maximization.')

    volts = geometry.description.get('voltage')
    if not volts: volts = 100

    energy = numpy.linspace(5, max(100, volts), n_bin)

    mu = model.linear_attenuation(energy, compound, density)
    exp_matrix = numpy.exp(-numpy.outer(length_0, mu))

    # Initial guess of the spectrum:
    spec = model.bremsstrahlung(energy, volts)
    spec *= model.scintillator_efficiency(energy, 'Si', rho=5, thickness=0.5)
    spec *= model.total_transmission(energy, 'H2O', 1, 1)
    spec *= energy
    spec /= spec.sum()

    #spec = numpy.ones_like(energy)
    #spec[0] = 0
    #spec[-1] = 0

    norm_sum = exp_matrix.sum(0)
    spec0 = spec.copy()
    #spec *= 0

    # exp_matrix at length == 0 is == 1. Sum of that is n_bin

    # EM type:
    for ii in range(iterations):
        frw = exp_matrix.dot(spec)

        epsilon = frw.max() / 100
        frw[frw < epsilon] = epsilon

        spec = spec * exp_matrix.T.dot(intensity_0 / frw) / norm_sum

        # Make sure that the total count of spec is 1 - that means intensity at length = 0 is equal to 1
        spec = spec / spec.sum()

    print('Spectrum computed.')

    #flexUtil.plot(length_0, title = 'thickness')
    #flexUtil.plot(mu, title = 'mu')
    #flexUtil.plot(_intensity, title = 'synth_counts')

    # synthetic intensity for a check:
    _intensity = exp_matrix.dot(spec)

    import matplotlib.pyplot as plt

    # Display:
    plt.figure()
    plt.semilogy(length[::200], intensity[::200], 'b.', lw=4, alpha=.8)
    plt.semilogy(length_0, intensity_0, 'g--')
    plt.semilogy(length_0, _intensity, 'r-', lw=3, alpha=.6)

    #plt.scatter(length[::100], -numpy.log(intensity[::100]), color='b', alpha=.2, s=4)
    plt.axis('tight')
    plt.title('Log intensity v.s. absorption length.')
    plt.legend(['raw', 'binned', 'solution'])
    plt.show()

    # Display:
    plt.figure()
    plt.plot(energy, spec, 'b')
    plt.plot(energy, spec0, 'r:')
    plt.axis('tight')
    plt.title('Calculated spectrum')
    plt.legend(['computed', 'initial guess'])
    plt.show()

    return energy, spec
예제 #17
0
from flexdata import display
from flexdata import data

from flextomo import projector
from flexcalc import process

#%% Read (short version for FlexRay data)

path = '/ufs/ciacc/flexbox/good'
proj, geom = process.process_flex(path, sample=4, skip=4)

#%% Read (longer, more general approach)

# Read:
path = '/ufs/ciacc/flexbox/good'
dark = data.read_stack(path, 'di00', sample=4)
flat = data.read_stack(path, 'io00', sample=4)
proj = data.read_stack(path, 'scan_', sample=4, skip=4)
geom = data.read_flexraylog(path, sample=4)

# Process:
proj = process.preprocess(proj, flat, dark, dim=1)
display.slice(proj, dim=0, bounds=[], title='Sinogram')

#%% Reconstruct uncorrected:

vol = projector.init_volume(proj)
projector.FDK(proj, vol, geom)

display.slice(vol, bounds=[], title='FDK Corrected')
예제 #18
0
# Define a simple projection geometry:
src2obj = 100  # mm
det2obj = 100  # mm
det_pixel = 0.001  # mm (1 micron)

geom = geometry.circular(src2obj, det2obj, det_pixel, ang_range=[0, 360])

# Create phantom (150 micron wide, 15 micron wall thickness):
vol = phantom.sphere(vol.shape, geom, 0.08)
vol -= phantom.sphere(vol.shape, geom, 0.07)

# Project:
projector.forwardproject(proj, vol, geom)

# Show:
display.slice(vol, title='Phantom')
display.slice(proj, dim=0, title='Sinogram')

#%% Get the material refraction index of calcium carbonate:

c = model.find_nist_name('Calcium Carbonate')
rho = c['density'] / 10

energy = 30  # KeV
n = model.material_refraction(energy, 'CaCO3', rho)

#%% Fresnel propagation for phase-contrast:

# Create Contrast Transfer Functions for phase contrast effect and detector blurring
phase_ctf = model.ctf(proj.shape[::2], 'fresnel',
                      [det_pixel, energy, src2obj, det2obj])
예제 #19
0
from flexcalc import analyze
from flexcalc import process

import numpy

#%% Short version of the spectral modeling:

# Geomtery:
geom = geometry.circular(src2obj=100,
                         det2obj=100,
                         det_pixel=0.2,
                         ang_range=[0, 360])

# This is our phantom:
vol = phantom.cuboid([1, 128, 128], geom, 8, 8, 8)
display.slice(vol, title='Phantom')

# Spectrum of the scanner:
kv = 90
filtr = {'material': 'Cu', 'density': 8, 'thickness': 0.1}
detector = {'material': 'Si', 'density': 5, 'thickness': 1}
E, S = model.effective_spectrum(kv=kv, filtr=filtr, detector=detector)

# Display:
display.plot(E, S, title='Effective spectrum')

# Materials list that corresponds to the number of labels in our phantom:
mats = [
    {
        'material': 'Al',
        'density': 2.7
예제 #20
0
import numpy

#%% Create volume and forward project into two orhogonal scans:
    
# Initialize images:    
proj_a = numpy.zeros([128, 32, 128], dtype = 'float32')
proj_b = numpy.zeros([128, 32, 128], dtype = 'float32')

# Define a simple projection geometry:
geom_a = geometry.circular(src2obj = 100, det2obj = 100, det_pixel = 0.01, ang_range = [0, 360])
geom_b = geom_a.copy()
geom_b['axs_roll'] = 90

# Create phantom and project into proj:
vol = phantom.random_spheroids([128, 128, 128], geom_a, number = 10)
display.slice(vol, title = 'Phantom')

# Forward project:
projector.forwardproject(proj_a, vol, geom_a)
projector.forwardproject(proj_b, vol, geom_b)

display.slice(proj_a, dim = 1, title = 'Proj A')
display.slice(proj_b, dim = 1, title = 'Proj B')

#%% Single-dataset SIRT:

vol_rec = numpy.zeros_like(vol)
projector.SIRT(proj_a, vol_rec, geom_a, iterations = 20)
display.slice(vol_rec, bounds = [0, 1], title = 'SIRT')

#%% Multi-dataset SIRT: