示例#1
0
def FISTA(projections, volume, geometry, iterations):
    '''
    FISTA reconstruction. Right now there is no TV minimization substep here!
    '''
    global settings
    preview = settings['preview']
    norm_update = settings['norm_update']

    # Sampling:
    samp = geometry['proj_sample']
    anisotropy = geometry['vol_sample']

    shp = numpy.array(projections.shape)
    shp //= samp

    prj_weight = 1 / (shp[1] * numpy.prod(anisotropy) * max(volume.shape))

    # Initialize L2:
    settings['norm'] = []
    t = 1

    volume_t = volume.copy()
    volume_old = volume.copy()

    print('FISTING in progress...')
    sleep(0.5)

    # Switch off progress bar if preview is on...
    if preview:
        ncols = 0
    else:
        ncols = 50

    for ii in tqdm(range(iterations), ncols=ncols):

        # Update volume:
        if sum(samp) > 3:
            proj = projections[::samp[0], ::samp[1], ::samp[2]]
            FISTA_step(proj, prj_weight, volume, volume_old, volume_t, t,
                       geometry)

        else:
            FISTA_step(projections, volume, volume_old, volume_t, t, geometry)

        # Preview
        if preview:
            display.display_slice(volume, dim=1)

    if norm_update:
        display.plot(settings['norm'], semilogy=True, title='Resudual norm')
示例#2
0
def SIRT(projections, volume, geometry, iterations):
    """
    Simultaneous Iterative Reconstruction Technique.
    """
    global settings
    preview = settings['preview']
    norm_update = settings['norm_update']

    # Sampling:
    samp = geometry['proj_sample']

    shp = numpy.array(projections.shape)
    shp //= samp

    # Initialize L2:
    settings['norm'] = []

    print('Feeling SIRTy...')
    sleep(0.5)

    # Switch off progress bar if preview is on...
    if preview:
        ncols = 0
    else:
        ncols = 50

    # Iterate:
    for ii in tqdm(range(iterations), ncols=ncols):

        # Update volume:
        if sum(samp) > 3:

            L2_step(projections[::samp[0], ::samp[1], ::samp[2]], volume,
                    geometry)

        else:
            L2_step(projections, volume, geometry)

        # Preview
        if preview:
            display.display_slice(volume, dim=1)

    if norm_update:
        display.plot(settings['norm'], semilogy=True, title='Resudual L2')
示例#3
0
def MULTI_SIRT(projections, volume, geometries, iterations):
    """
    A multi-dataset version of SIRT. Here prjections and geometries are lists.
    """
    global settings
    preview = settings['preview']
    norm_update = settings['norm_update']
    norm = settings['norm']

    # Make sure array is contiguous (if not memmap):
    # if not isinstance(projections, numpy.memmap):
    #    projections = numpy.ascontiguousarray(projections)

    # Initialize L2:
    norm = []

    print('Doing SIRT`y things...')
    sleep(0.5)

    # Switch off progress bar if preview is on...
    if preview:
        ncols = 0
    else:
        ncols = 50

    for ii in tqdm(range(iterations), ncols=ncols):

        norm = 0
        for ii, proj in enumerate(projections):

            # This weight is half of the normal weight to make sure convergence is ok:
            #prj_weight = 1 / (proj.shape[1] * max(volume.shape))

            # Update volume:
            L2_step(proj, volume, geometries[ii])

        # Preview
        if preview:
            display.display_slice(volume, dim=1)

    if norm_update:
        display.plot(norm, semilogy=True, title='Resudual norm')
示例#4
0
def EM(projections, volume, geometry, iterations):
    """
    Expectation Maximization
    """
    global settings
    preview = settings['preview']
    norm_update = settings['norm_update']

    # Make sure that the volume is positive:
    if volume.max() <= 0:
        volume *= 0
        volume += 1
    elif volume.min() < 0:
        volume[volume < 0] = 0

    projections[projections < 0] = 0

    # Initialize L2:
    settings['norm'] = []

    print('Em Emm Emmmm...')
    sleep(0.5)

    # Switch off progress bar if preview is on...
    if preview:
        ncols = 0
    else:
        ncols = 50

    # Go!
    for ii in tqdm(range(iterations), ncols=ncols):

        # Update volume:
        EM_step(projections, volume, geometry)

        # Preview
        if preview:
            display.display_slice(volume, dim=1)

    if norm_update:
        display.plot(settings['norm'], semilogy=True, title='Resudual norm')
示例#5
0
import numpy

#%% Create volume and forward project:
    
# Initialize images:    
proj = numpy.zeros([1, 361, 512], dtype = 'float32')

# Define a simple projection geometry:
geometry = io.init_geometry(src2obj = 100, det2obj = 100, det_pixel = 0.01, theta_range = [0, 360], geom_type = 'simple')

print('Volume width is:', 512 * geometry['img_pixel'])

# Create phantom and project into proj:
vol = phantom.abstract_nudes([1, 512, 512], geometry, complexity = 10)

display.display_slice(vol, title = 'Phantom')

# Forward project:
project.forwardproject(proj, vol, geometry)
display.display_slice(proj, title = 'Sinogram')

#%% Unfiltered back-project

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

# Backproject:
project.settings['block_number'] = 1
project.backproject(proj, vol_rec, geometry)

display.display_slice(vol_rec, title = 'Backprojection')
from flexcalc import spectrum
from flexcalc import process

import numpy
   
#%% Define a simple projection geometry:

geometry = io.init_geometry(src2obj = 100, det2obj = 100, det_pixel = 0.2, 
                            theta_range = [0, 360], geom_type = 'simple')

#%% Short version of the spectral modeling:

# This is our phantom:
vol = phantom.cuboid([1,128,128], geometry, 8,8,8)  
display.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 = spectrum.effective_spectrum(kv = 90, filtr = filtr, detector = detector)  

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

# Materials list that corresponds to the number of labels in our phantom:  
mats = [{'material':'Al', 'density':2.7},]
        
# Sinogram that will be simultated:
counts = numpy.zeros([1, 128, 128], dtype = 'float32')
path = '/ufs/ciacc/flexbox/al_test/90KV_no_filt/'

dark = io.read_tiffs(path, 'di00')
flat = io.read_tiffs(path, 'io00')
proj = io.read_tiffs(path, 'scan_')

meta = io.read_meta(path, 'flexray')

#%% Prepro:

proj = (proj - dark) / (flat.mean(0) - dark)
proj = -numpy.log(proj)

proj = array.raw2astra(proj)

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

#%% FDK Recon

vol = project.init_volume(proj)
project.FDK(proj, vol, meta['geometry'])

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

#%% EM

vol = numpy.ones([10, 2000, 2000], dtype='float32')

project.EM(proj, vol, meta['geometry'], iterations=3)

display.display_slice(vol, title='EM')
示例#8
0
# Compute the spectrum of the system using data @ path:
# It is assumed that the data provided has a sample made of a single material (see 'compound' parameter)

energy, spectrum = process.data_to_spectrum(path, compound = 'Al', density = 2.7)

#%% Read data, reconstruct uncorrected:

# Read:
proj, meta = process.process_flex(path, sample = 2, skip = 2)

# Reconstruct:
vol = project.init_volume(proj)

project.FDK(proj, vol, meta['geometry'])

display.display_slice(vol, title = 'Uncorrected FDK')

a,b = process.histogram(vol, rng = [-0.05, 0.15])

#%% Calibrate: 

proj = process.equivalent_density(proj, meta, energy, spectrum, compound = 'Al', density = 2.7) 

#%% Reconstruct corrected:

vol = project.init_volume(proj)

project.FDK(proj, vol, meta['geometry'])

display.display_slice(vol, title = 'Corrected FDK')
示例#9
0
path = '/ufs/ciacc/flexbox/al_test/90KV_no_filt/'

dark = io.read_tiffs(path, 'di00')
flat = io.read_tiffs(path, 'io00')
proj = io.read_tiffs(path, 'scan_')

meta = io.read_meta(path, 'flexray')

#%% Prepro:

proj = (proj - dark) / (flat.mean(0) - dark)
proj = -numpy.log(proj)

proj = array.raw2astra(proj)

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

#%% Recon:

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

# Initialize ASTRA geometries:
vol_geom = io.astra_vol_geom(meta['geometry'], vol.shape)
proj_geom = io.astra_proj_geom(meta['geometry'], proj.shape)

# This is ASTRAAA!!!
sin_id = astra.data3d.link('-sino', proj_geom, numpy.ascontiguousarray(proj))
vol_id = astra.data3d.link('-vol', vol_geom, numpy.ascontiguousarray(vol))

cfg = astra.astra_dict('FDK_CUDA')
cfg['ReconstructionDataId'] = vol_id
示例#10
0
meta = io.read_meta(path, 'flexray')

#%% Prepro:

# Now, since the data is on the harddisk, we shouldn't lose the pointer to it!
# Be careful which operations to apply. Implicit are OK.
proj -= dark
proj /= (flat.mean(0) - dark)

numpy.log(proj, out=proj)
proj *= -1

proj = array.raw2astra(proj)

display.display_slice(proj)

#%% Recon

vol = numpy.zeros([50, 1000, 1000], dtype='float32')

# Split the data into 20 subsets:
project.settings['block_number'] = 20

project.FDK(proj, vol, meta['geometry'])

display.display_slice(vol)

#%% SIRT

vol = numpy.ones([50, 1000, 1000], dtype='float32')
# Name and range of the parameter to optimize:
key = 'det_rot'
trial_values = numpy.linspace(-0.01, 0.01, 11)

# Subsampling of data (vertical x 10)
samp = [5, 1, 1]

# Optimization:
guess = process.optimize_modifier(trial_values,
                                  proj,
                                  meta['geometry'],
                                  samp=samp,
                                  key=key,
                                  preview=True)

#%% Reconstruct uncorrected:

vol = project.init_volume(proj)
project.FDK(proj, vol, meta['geometry'])

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

#%% REconstruct corrected:

meta['geometry'][key] = guess

vol = project.init_volume(proj)
project.FDK(proj, vol, meta['geometry'])

display.display_slice(vol, bounds=[], title='FDK Corrected')
示例#12
0
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Load a standard CT scan. Use flexCALC.process to preprocess the data.
"""
#%% Imports

from flexcalc import process

from flexdata import display

from flextomo import project

#%% Read data:

path = '/ufs/ciacc/flexbox/al_test/90KV_no_filt/'

proj, meta = process.process_flex(path, skip=4, sample=4)

#%% FDK:

vol = project.init_volume(proj)
project.FDK(proj, vol, meta['geometry'])

display.display_slice(vol, bounds=[], title='FDK')
vol = numpy.zeros([1, h, h], dtype='float32')
proj = numpy.zeros([1, 361, h], dtype='float32')

# Define a simple projection geometry:
src2obj = 100  # mm
det2obj = 100  # mm
det_pixel = 0.001 / x  # mm (1 micron)

geometry = io.init_geometry(src2obj, det2obj, det_pixel, [0, 360])

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

# Show:
display.display_slice(vol, title='Phantom')

# Project:
project.forwardproject(proj, vol, geometry)

#%%
# Get the material refraction index:
c = spectrum.find_nist_name('Calcium Carbonate')
rho = c['density'] / 10

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

#%% Proper Fresnel propagation for phase-contrast:

# Create Contrast Transfer Functions for phase contrast effect and detector blurring
示例#14
0
#%% Read the data

path = '/ufs/ciacc/flexbox/JINR_data/projections/SPos0/Energy150000/'
proj = io.read_tiffs(path, '00')

# Transpose for ASTRA compatibility:
proj = array.raw2astra(proj)

# Get rid of funny values:
proj[(~numpy.isfinite(proj)) | (proj < 0.1)] = 1
proj[proj > 1] = 1

# Da Holy LOG:
proj = -numpy.log(proj)

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

#%% Create geometry:

# We don't have a dedicated parser for JINR geometry description file.
# so we will simply make an ASTRA geometry by hand
'''
Mode = cone beam
Last angle = 360�
Pixel size = 0.055 mm
Centre of rotation = 1034.82
Source object distance = 120 mm
Source detector distance = 220 mm
Direction of rotation = counter-clockwise
Vertical centre = 203