def transform_scalars(dataset): """3D Reconstruct from a tilt series using constraint-based Direct Fourier Method""" from tomviz import utils import numpy as np ###Niter### ###Niter_update_support### ###supportSigma### ###supportThreshold### #percent supportThreshold = supportThreshold/100.0 nonnegativeVoxels = True tilt_angles = utils.get_tilt_angles(dataset) #Get Tilt angles tilt_images = utils.get_array(dataset) if tilt_images is None: raise RuntimeError("No scalars found!") #Direct Fourier recon without constraints (recon,recon_F) = dfm3(tilt_images,tilt_angles,np.size(tilt_images,0)*2) kr_cutoffs = np.linspace(0.05,0.5,10); I_data = radial_average(tilt_images,kr_cutoffs) #average Fourier magnitude of tilt series as a function of kr #Search for solutions that satisfy additional constraints recon = difference_map_update(recon_F,nonnegativeVoxels,I_data,kr_cutoffs,Niter,Niter_update_support,supportSigma,supportThreshold) print('Reconsruction Complete') # Set the result as the new scalars. utils.set_array(dataset, recon) # Mark dataset as volume utils.mark_as_volume(dataset)
def transform_scalars(dataset): """3D Reconstruct from a tilt series using Weighted Back-projection Method""" from tomviz import utils import numpy as np interpolation_methods = ('linear', 'nearest', 'spline', 'cubic') filter_methods = ('none', 'ramp', 'shepp-logan', 'cosine', 'hamming', 'hann') ###Nrecon### ###filter### ###interp### # Get Tilt angles tilt_angles = utils.get_tilt_angles(dataset) data_py = utils.get_array(dataset) if data_py is None: raise RuntimeError("No scalars found!") recon = wbp3(data_py, tilt_angles, Nrecon, filter_methods[filter], interpolation_methods[interp]) print('Reconsruction Complete') # Set the result as the new scalars. utils.set_array(dataset, recon) # Mark dataset as volume. utils.mark_as_volume(dataset)
def transform_scalars(dataset): """Downsample volume by a factor of 2""" from tomviz import utils import scipy.ndimage array = utils.get_array(dataset) # Downsample the dataset x2 using order 1 spline (linear) result = scipy.ndimage.interpolation.zoom(array, (0.5, 0.5, 0.5), output=None, order=1, mode='constant', cval=0.0, prefilter=False) # Set the result as the new scalars. utils.set_array(dataset, result) # Update tilt angles if dataset is a tilt series. try: tilt_angles = utils.get_tilt_angles(dataset) tilt_angles = scipy.ndimage.interpolation.zoom(tilt_angles, 0.5) utils.set_tilt_angles(dataset, tilt_angles) except: # noqa # TODO What exception are we ignoring? pass
def transform_scalars(dataset): """Resample dataset""" from tomviz import utils import numpy as np import scipy.ndimage #----USER SPECIFIED VARIABLES-----# #resampingFactor = [1,1,1] #Specify the shifts (x,y,z) applied to data ###resampingFactor### #---------------------------------# array = utils.get_array(dataset) # Transform the dataset. result = scipy.ndimage.interpolation.zoom(array, resampingFactor) # Set the result as the new scalars. utils.set_array(dataset, result) # Update tilt angles if dataset is a tilt series. if resampingFactor[2] != 1: try: tilt_angles = utils.get_tilt_angles(dataset) tilt_angles = scipy.ndimage.interpolation.zoom(tilt_angles, resampingFactor[2]) utils.set_tilt_angles(dataset, tilt_angles) except: pass
def transform_scalars(dataset, resampling_factor=[1, 1, 1]): """Resample dataset""" from tomviz import utils import scipy.ndimage import numpy as np array = utils.get_array(dataset) # Transform the dataset. result_shape = utils.zoom_shape(array, resampling_factor) result = np.empty(result_shape, array.dtype, order='F') scipy.ndimage.interpolation.zoom(array, resampling_factor, output=result) # Set the result as the new scalars. utils.set_array(dataset, result) # Update tilt angles if dataset is a tilt series. if resampling_factor[2] != 1: try: tilt_angles = utils.get_tilt_angles(dataset) result_shape = utils.zoom_shape(tilt_angles, resampling_factor[2]) result = np.empty(result_shape, array.dtype, order='F') scipy.ndimage.interpolation.zoom(tilt_angles, resampling_factor[2], output=result) utils.set_tilt_angles(dataset, result) except: # noqa # TODO What exception are we ignoring? pass
def transform_scalars(dataset, resampling_factor=[1, 1, 1]): """Resample dataset""" from tomviz import utils import scipy.ndimage import numpy as np array = utils.get_array(dataset) # Transform the dataset. result_shape = utils.zoom_shape(array, resampling_factor) result = np.empty(result_shape, array.dtype, order='F') scipy.ndimage.interpolation.zoom(array, resampling_factor, output=result) # Set the result as the new scalars. utils.set_array(dataset, result) # Update tilt angles if dataset is a tilt series. if resampling_factor[2] != 1: try: tilt_angles = utils.get_tilt_angles(dataset) result_shape = utils.zoom_shape(tilt_angles, resampling_factor[2]) result = np.empty(result_shape, array.dtype, order='F') scipy.ndimage.interpolation.zoom( tilt_angles, resampling_factor[2], output=result) utils.set_tilt_angles(dataset, result) except: # noqa # TODO What exception are we ignoring? pass
def transform_scalars(dataset): """3D Reconstruct from a tilt series using Weighted Back-projection Method""" from tomviz import utils import numpy as np interpolation_methods = ('linear','nearest','spline','cubic') filter_methods = ('none','ramp','shepp-logan','cosine','hamming','hann') ###Nrecon### ###filter### ###interp### #Get Tilt angles tilt_angles = utils.get_tilt_angles(dataset) data_py = utils.get_array(dataset) if data_py is None: raise RuntimeError("No scalars found!") recon = wbp3(data_py,tilt_angles,Nrecon,filter_methods[filter],interpolation_methods[interp]) print('Reconsruction Complete') # set the result as the new scalars. utils.set_array(dataset, recon) # Mark dataset as volume utils.mark_as_volume(dataset)
def transform_scalars(dataset): """Delete Slices in Dataset""" from tomviz import utils import numpy as np axis = 0; #----USER SPECIFIED VARIABLES-----# ###firstSlice### ###lastSlice### ###axis### #Axis along which to delete the subarray #---------------------------------# #get current dataset array = utils.get_array(dataset) #Get indices of the slices to be deleted indices = np.linspace(firstSlice,lastSlice,lastSlice-firstSlice+1).astype(int) # delete slices array = np.delete(array,indices,axis) #set the result as the new scalars. utils.set_array(dataset, array) #Delete corresponding tilt anlges if dataset is a tilt series if axis == 2: try: tilt_angles = utils.get_tilt_angles(dataset) tilt_angles = np.delete(tilt_angles,indices) utils.set_tilt_angles(dataset, tilt_angles) except: pass
def transform_scalars(dataset): """Resample dataset""" from tomviz import utils import numpy as np import scipy.ndimage #----USER SPECIFIED VARIABLES-----# #resampingFactor = [1,1,1] #Specify the shifts (x,y,z) applied to data ###resampingFactor### #---------------------------------# array = utils.get_array(dataset) # transform the dataset result = scipy.ndimage.interpolation.zoom(array, resampingFactor) # set the result as the new scalars. utils.set_array(dataset, result) #Update tilt angles if dataset is a tilt series if resampingFactor[2] != 1: try: tilt_angles = utils.get_tilt_angles(dataset) tilt_angles = scipy.ndimage.interpolation.zoom(tilt_angles, resampingFactor[2]) utils.set_tilt_angles(dataset, tilt_angles) except: pass
def transform_scalars(dataset, firstSlice=None, lastSlice=None, axis=2): """Delete Slices in Dataset""" from tomviz import utils import numpy as np # Get the current dataset. array = utils.get_array(dataset) # Get indices of the slices to be deleted. indices = np.linspace(firstSlice, lastSlice, lastSlice - firstSlice + 1).astype(int) # Delete the specified slices. array = np.delete(array, indices, axis) # Set the result as the new scalars. utils.set_array(dataset, array) # Delete corresponding tilt anlges if dataset is a tilt series. if axis == 2: try: tilt_angles = utils.get_tilt_angles(dataset) tilt_angles = np.delete(tilt_angles, indices) utils.set_tilt_angles(dataset, tilt_angles) except: # noqa # TODO what exception are we ignoring here? pass
def transform_scalars(dataset): """Pad dataset""" from tomviz import utils import numpy as np #----USER SPECIFIED VARIABLES-----# ###padWidthX### ###padWidthY### ###padWidthZ### ###padMode_index### #---------------------------------# padModes = ['constant','edge','wrap','minimum','median'] padMode = padModes[padMode_index] array = utils.get_array(dataset) #get data as numpy array if array is None: #Check if data exists raise RuntimeError("No data array found!") pad_width = (padWidthX,padWidthY,padWidthZ) # pad the data. array = np.lib.pad(array, pad_width, padMode) # Set the data so that it is visible in the application. utils.set_array(dataset, array) # If dataset is marked as tilt series, update tilt angles if padWidthZ[0]+padWidthZ[1] >0: try: tilt_angles = utils.get_tilt_angles(dataset) tilt_angles = np.lib.pad(tilt_angles,padWidthZ, padMode) utils.set_tilt_angles(dataset, tilt_angles) except: pass
def transform_scalars(dataset): """3D Reconstruct from a tilt series using Algebraic Reconstruction Technique (ART)""" ###Niter### #Get Tilt angles tiltAngles = utils.get_tilt_angles(dataset) #Get Tilt Series tiltSeries = utils.get_array(dataset) (Nslice, Nray, Nproj) = tiltSeries.shape if tiltSeries is None: raise RuntimeError("No scalars found!") #Generate measurement matrix A = parallelRay(Nray, 1.0, tiltAngles, Nray, 1.0) #A is a sparse matrix recon = np.zeros((Nslice, Nray, Nray)) art3(A.todense(), tiltSeries, recon, Niter) # set the result as the new scalars. utils.set_array(dataset, recon) # Mark dataset as volume utils.mark_as_volume(dataset)
def transform_scalars(dataset): """3D Reconstruct from a tilt series using Algebraic Reconstruction Technique (ART)""" ###Niter### # Get Tilt angles tiltAngles = utils.get_tilt_angles(dataset) # Get Tilt Series tiltSeries = utils.get_array(dataset) (Nslice,Nray,Nproj) = tiltSeries.shape if tiltSeries is None: raise RuntimeError("No scalars found!") # Generate measurement matrix A = parallelRay(Nray,1.0,tiltAngles,Nray,1.0) #A is a sparse matrix recon = np.zeros((Nslice,Nray,Nray)) art3(A.todense(),tiltSeries,recon,Niter) # Set the result as the new scalars. utils.set_array(dataset, recon) # Mark dataset as volume utils.mark_as_volume(dataset)
def transform_scalars(self, dataset, Nrecon=None, filter=None, interp=None): """ 3D Reconstruct from a tilt series using Weighted Back-projection Method """ self.progress.maximum = 1 from tomviz import utils interpolation_methods = ('linear', 'nearest', 'spline', 'cubic') filter_methods = ('none', 'ramp', 'shepp-logan', 'cosine', 'hamming', 'hann') # Get Tilt angles tilt_angles = utils.get_tilt_angles(dataset) tiltSeries = utils.get_array(dataset) if tiltSeries is None: raise RuntimeError("No scalars found!") Nslice = tiltSeries.shape[0] self.progress.maximum = Nslice step = 0 recon = np.empty([Nslice, Nrecon, Nrecon], dtype=float, order='F') t0 = time.time() counter = 1 etcMessage = 'Estimated time to complete: n/a' for i in range(Nslice): if self.canceled: return self.progress.message = 'Slice No.%d/%d. ' % (i + 1, Nslice) + etcMessage recon[i, :, :] = wbp2(tiltSeries[i, :, :], tilt_angles, Nrecon, filter_methods[filter], interpolation_methods[interp]) step += 1 self.progress.value = step timeLeft = (time.time() - t0) / counter * (Nslice - counter) counter += 1 timeLeftMin, timeLeftSec = divmod(timeLeft, 60) timeLeftHour, timeLeftMin = divmod(timeLeftMin, 60) etcMessage = 'Estimated time to complete: %02d:%02d:%02d' % ( timeLeftHour, timeLeftMin, timeLeftSec) # Set up the output dataset from vtk import vtkImageData recon_dataset = vtkImageData() recon_dataset.CopyStructure(dataset) utils.set_array(recon_dataset, recon) utils.mark_as_volume(recon_dataset) returnValues = {} returnValues["reconstruction"] = recon_dataset return returnValues
def transform_scalars(dataset): """Delete Slices in Dataset""" from tomviz import utils import numpy as np axis = 0; #----USER SPECIFIED VARIABLES-----# ###firstSlice### ###lastSlice### ###axis### #Axis along which to delete the subarray #---------------------------------# # Get the current dataset. array = utils.get_array(dataset) # Get indices of the slices to be deleted. indices = np.linspace(firstSlice,lastSlice,lastSlice-firstSlice+1).astype(int) # Delete the specified slices. array = np.delete(array,indices,axis) # Set the result as the new scalars. utils.set_array(dataset, array) # Delete corresponding tilt anlges if dataset is a tilt series. if axis == 2: try: tilt_angles = utils.get_tilt_angles(dataset) tilt_angles = np.delete(tilt_angles,indices) utils.set_tilt_angles(dataset, tilt_angles) except: pass
def transform_scalars(dataset): """Downsample volume by a factor of 2""" from tomviz import utils import scipy.ndimage import numpy as np array = utils.get_array(dataset) # Downsample the dataset x2 using order 1 spline (linear) # Calculate out array shape zoom = (0.5, 0.5, 0.5) result_shape = utils.zoom_shape(array, zoom) result = np.empty(result_shape, array.dtype, order='F') scipy.ndimage.interpolation.zoom(array, zoom, output=result, order=1, mode='constant', cval=0.0, prefilter=False) # Set the result as the new scalars. utils.set_array(dataset, result) # Update tilt angles if dataset is a tilt series. try: tilt_angles = utils.get_tilt_angles(dataset) result_shape = utils.zoom_shape(tilt_angles, 0.5) result = np.empty(result_shape, array.dtype, order='F') tilt_angles = scipy.ndimage.interpolation.zoom(tilt_angles, 0.5, output=result) utils.set_tilt_angles(dataset, result) except: # noqa # TODO What exception are we ignoring? pass
def transform_scalars(self, dataset): """Automatically align tilt images by cross-correlation""" self.progress.maximum = 1 tiltSeries = utils.get_array(dataset).astype(float) tiltAngles = utils.get_tilt_angles(dataset) # determine reference image index zeroDegreeTiltImage = np.where(tiltAngles == 0)[0] if zeroDegreeTiltImage: referenceIndex = zeroDegreeTiltImage[0] else: referenceIndex = tiltSeries.shape[2] // 2 # create Fourier space filter filterCutoff = 4 (Ny, Nx, Nproj) = tiltSeries.shape ky = np.fft.fftfreq(Ny) kx = np.fft.fftfreq(Nx) [kX, kY] = np.meshgrid(kx, ky) kR = np.sqrt(kX**2 + kY**2) kFilter = (kR <= (0.5 / filterCutoff)) * \ np.sin(2 * filterCutoff * np.pi * kR)**2 # create real sapce filter to remove edge discontinuities y = np.linspace(1, Ny, Ny) x = np.linspace(1, Nx, Nx) [X, Y] = np.meshgrid(x, y) rFilter = (np.sin(np.pi * X / Nx) * np.sin(np.pi * Y / Ny))**2 self.progress.maximum = tiltSeries.shape[2] - 1 step = 1 for i in range(referenceIndex, Nproj - 1): if self.canceled: return self.progress.message = 'Processing tilt image No.%d/%d' % (step, Nproj) tiltSeries[:, :, i + 1] = crossCorrelationAlign(tiltSeries[:, :, i + 1], tiltSeries[:, :, i], rFilter, kFilter) step += 1 self.progress.value = step for i in range(referenceIndex, 0, -1): if self.canceled: return self.progress.message = 'Processing tilt image No.%d/%d' % (step, Nproj) tiltSeries[:, :, i - 1] = crossCorrelationAlign(tiltSeries[:, :, i - 1], tiltSeries[:, :, i], rFilter, kFilter) step += 1 self.progress.value = step utils.set_array(dataset, tiltSeries)
def transform_scalars(self, dataset, Niter=None, stepSize=None, updateMethodIndex=None): """ 3D Reconstruct from a tilt series using Simultaneous Iterative Reconstruction Techniques (SIRT)""" self.progress.maximum = 1 update_methods = ('landweber', 'cimmino', 'component averaging') #reference """L. Landweber, Amer. J. Math., 73 (1951), pp. 615–624""" """G. Cimmino, La Ric. Sci., XVI, Ser. II, Anno IX, 1 (1938), pp. 326–333 """ """Y. Censor et al, Parallel Comput., 27 (2001), pp. 777–808""" # Get Tilt angles tiltAngles = utils.get_tilt_angles(dataset) #remove zero tilt anlges if np.count_nonzero(tiltAngles) < tiltAngles.size: tiltAngles = tiltAngles + 0.001 # Get Tilt Series tiltSeries = utils.get_array(dataset) (Nslice, Nray, Nproj) = tiltSeries.shape if tiltSeries is None: raise RuntimeError("No scalars found!") # Generate measurement matrix self.progress.message = 'Generating measurement matrix' A = parallelRay(Nray, 1.0, tiltAngles, Nray, 1.0) #A is a sparse matrix recon = np.zeros((Nslice, Nray, Nray)) self.progress.maximum = Nslice + 1 step = 0 #create a reconstruction object r = SIRT(A, update_methods[updateMethodIndex]) r.initialize() step += 1 self.progress.value = step for s in range(Nslice): if self.canceled: return b = tiltSeries[s, :, :].transpose().flatten() self.progress.message = 'Slice No.%d/%d' % (s + 1, Nslice) recon[s, :, :] = r.recon2(b, Niter, stepSize).reshape((Nray, Nray)) step += 1 self.progress.value = step # Set the result as the new scalars. utils.set_array(dataset, recon) # Mark dataset as volume utils.mark_as_volume(dataset)
def transform_scalars(self, dataset, Nrecon=None, filter=None, interp=None): """ 3D Reconstruct from a tilt series using Weighted Back-projection Method """ self.progress.maximum = 1 from tomviz import utils interpolation_methods = ('linear', 'nearest', 'spline', 'cubic') filter_methods = ('none', 'ramp', 'shepp-logan', 'cosine', 'hamming', 'hann') # Get Tilt angles tilt_angles = utils.get_tilt_angles(dataset) tiltSeries = utils.get_array(dataset) if tiltSeries is None: raise RuntimeError("No scalars found!") Nslice = tiltSeries.shape[0] self.progress.maximum = Nslice step = 0 recon = np.empty([Nslice, Nrecon, Nrecon], dtype=float, order='F') t0 = time.time() counter = 1 etcMessage = 'Estimated time to complete: n/a' for i in range(Nslice): if self.canceled: return self.progress.message = 'Slice No.%d/%d. ' % ( i + 1, Nslice) + etcMessage recon[i, :, :] = wbp2(tiltSeries[i, :, :], tilt_angles, Nrecon, filter_methods[filter], interpolation_methods[interp]) step += 1 self.progress.value = step timeLeft = (time.time() - t0) / counter * (Nslice - counter) counter += 1 timeLeftMin, timeLeftSec = divmod(timeLeft, 60) timeLeftHour, timeLeftMin = divmod(timeLeftMin, 60) etcMessage = 'Estimated time to complete: %02d:%02d:%02d' % ( timeLeftHour, timeLeftMin, timeLeftSec) # Set up the output dataset from vtk import vtkImageData recon_dataset = vtkImageData() recon_dataset.CopyStructure(dataset) utils.set_array(recon_dataset, recon) utils.mark_as_volume(recon_dataset) returnValues = {} returnValues["reconstruction"] = recon_dataset return returnValues
def transform_scalars(self, dataset): """Automatically align tilt images by cross-correlation""" self.progress.maximum = 1 tiltSeries = utils.get_array(dataset).astype(float) tiltAngles = utils.get_tilt_angles(dataset) # determine reference image index zeroDegreeTiltImage = np.where(tiltAngles == 0)[0] if zeroDegreeTiltImage: referenceIndex = zeroDegreeTiltImage[0] else: referenceIndex = tiltSeries.shape[2] // 2 # create Fourier space filter filterCutoff = 4 (Ny, Nx, Nproj) = tiltSeries.shape ky = np.fft.fftfreq(Ny) kx = np.fft.fftfreq(Nx) [kX, kY] = np.meshgrid(kx, ky) kR = np.sqrt(kX**2 + kY**2) kFilter = (kR <= (0.5 / filterCutoff)) * \ np.sin(2 * filterCutoff * np.pi * kR)**2 # create real sapce filter to remove edge discontinuities y = np.linspace(1, Ny, Ny) x = np.linspace(1, Nx, Nx) [X, Y] = np.meshgrid(x, y) rFilter = (np.sin(np.pi * X / Nx) * np.sin(np.pi * Y / Ny)) ** 2 self.progress.maximum = tiltSeries.shape[2] - 1 step = 0 for i in range(referenceIndex, Nproj - 1): if self.canceled: return self.progress.message = 'Processing tilt image No.%d/%d' % ( i + 1, Nproj) tiltSeries[:, :, i + 1] = crossCorrelationAlign( tiltSeries[:, :, i + 1], tiltSeries[:, :, i], rFilter, kFilter) step += 1 self.progress.value = step for i in range(referenceIndex, 0, -1): if self.canceled: return self.progress.message = 'Processing tilt image No.%d/%d' % ( i, Nproj) tiltSeries[:, :, i - 1] = crossCorrelationAlign( tiltSeries[:, :, i - 1], tiltSeries[:, :, i], rFilter, kFilter) step += 1 self.progress.value = step utils.set_array(dataset, tiltSeries)
def transform_scalars(self, dataset): """Automatic align the tilt axis to the center of images""" self.progress.maximum = 1 from tomviz import utils # Get Tilt angles tilt_angles = utils.get_tilt_angles(dataset) tiltSeries = utils.get_array(dataset) if tiltSeries is None: raise RuntimeError("No scalars found!") Nx, Ny, Nz = tiltSeries.shape shifts = (np.linspace(-20, 20, 41)).astype('int') numberOfSlices = 5 # number of slices used for recon # randomly choose slices with top 50% total intensities tiltSeriesSum = np.sum(tiltSeries, axis=(1, 2)) temp = tiltSeriesSum.argsort()[Nx // 2:] slices = temp[np.random.permutation(temp.size)[:numberOfSlices]] print('Reconstruction slices:') print(slices) I = np.zeros(shifts.size) self.progress.maximum = shifts.size - 1 step = 0 for i in range(shifts.size): if self.canceled: return shiftedTiltSeries = np.roll(tiltSeries[slices, :, :, ], shifts[i], axis=1) for s in range(numberOfSlices): self.progress.message = ('Reconstructing slice No.%d with %d ' 'pixels shift' % (slices[s], shifts[i])) recon = wbp2(shiftedTiltSeries[s, :, :], tilt_angles, Ny, 'ramp', 'linear') I[i] = I[i] + np.amax(recon) step += 1 self.progress.value = step print('shift: %d' % shifts[np.argmax(I)]) result = np.roll(tiltSeries, shifts[np.argmax(I)], axis=1) result = np.asfortranarray(result) # Set the result as the new scalars. utils.set_array(dataset, result)
def transform_scalars(self, dataset): """Automatic align the tilt axis to the center of images""" self.progress.maximum = 1 from tomviz import utils # Get Tilt angles tilt_angles = utils.get_tilt_angles(dataset) tiltSeries = utils.get_array(dataset) if tiltSeries is None: raise RuntimeError("No scalars found!") Nx, Ny, Nz = tiltSeries.shape shifts = (np.linspace(-20, 20, 41)).astype('int') numberOfSlices = 5 # number of slices used for recon # randomly choose slices with top 50% total intensities tiltSeriesSum = np.sum(tiltSeries, axis=(1, 2)) temp = tiltSeriesSum.argsort()[Nx // 2:] slices = temp[np.random.permutation(temp.size)[:numberOfSlices]] print('Reconstruction slices:') print(slices) I = np.zeros(shifts.size) self.progress.maximum = shifts.size - 1 step = 0 for i in range(shifts.size): if self.canceled: return shiftedTiltSeries = np.roll( tiltSeries[slices, :, :, ], shifts[i], axis=1) for s in range(numberOfSlices): self.progress.message = ('Reconstructing slice No.%d with %d ' 'pixels shift' % (slices[s], shifts[i])) recon = wbp2(shiftedTiltSeries[s, :, :], tilt_angles, Ny, 'ramp', 'linear') I[i] = I[i] + np.amax(recon) step += 1 self.progress.value = step print('shift: %d' % shifts[np.argmax(I)]) result = np.roll(tiltSeries, shifts[np.argmax(I)], axis=1) result = np.asfortranarray(result) # Set the result as the new scalars. utils.set_array(dataset, result)
def transform_scalars(self, dataset, Nrecon=None, filter=None, interp=None): """ 3D Reconstruct from a tilt series using Weighted Back-projection Method """ self.progress.maximum = 1 from tomviz import utils interpolation_methods = ('linear', 'nearest', 'spline', 'cubic') filter_methods = ('none', 'ramp', 'shepp-logan', 'cosine', 'hamming', 'hann') # Get Tilt angles tilt_angles = utils.get_tilt_angles(dataset) tiltSeries = utils.get_array(dataset) if tiltSeries is None: raise RuntimeError("No scalars found!") Nslice = tiltSeries.shape[0] self.progress.maximum = Nslice step = 0 recon = np.zeros((Nslice, Nrecon, Nrecon)) for i in range(Nslice): if self.canceled: return self.progress.message = 'Slice No.%d/%d' % (i + 1, Nslice) recon[i, :, :] = wbp2(tiltSeries[i, :, :], tilt_angles, Nrecon, filter_methods[filter], interpolation_methods[interp]) step += 1 self.progress.value = step print('Reconsruction Complete') # Set up the output dataset from vtk import vtkImageData recon_dataset = vtkImageData() recon_dataset.CopyStructure(dataset) utils.set_array(recon_dataset, recon) utils.mark_as_volume(recon_dataset) returnValues = {} returnValues["reconstruction"] = recon_dataset return returnValues
def transform_scalars(dataset, pad_size_before=[0, 0, 0], pad_size_after=[0, 0, 0], pad_mode_index=0): """Pad dataset""" from tomviz import utils import numpy as np padModes = ['constant', 'edge', 'wrap', 'minimum', 'median'] padMode = padModes[pad_mode_index] array = utils.get_array(dataset) #get data as numpy array if array is None: #Check if data exists raise RuntimeError("No data array found!") padWidthX = (pad_size_before[0], pad_size_after[0]) padWidthY = (pad_size_before[1], pad_size_after[1]) padWidthZ = (pad_size_before[2], pad_size_after[2]) pad_width = (padWidthX, padWidthY, padWidthZ) result_shape = np.zeros(3, dtype=int) result_shape[0] = array.shape[0] + pad_size_before[0] + pad_size_after[0] result_shape[1] = array.shape[1] + pad_size_before[1] + pad_size_after[1] result_shape[2] = array.shape[2] + pad_size_before[2] + pad_size_after[2] result = np.empty(result_shape, array.dtype, order='F') # pad the data. result[:] = np.lib.pad(array, pad_width, padMode) # Set the data so that it is visible in the application. extent = list(dataset.GetExtent()) start = [x - y for (x, y) in zip(extent[0::2], pad_size_before)] utils.set_array(dataset, result, start) # If dataset is marked as tilt series, update tilt angles if padWidthZ[0] + padWidthZ[1] > 0: try: tilt_angles = utils.get_tilt_angles(dataset) tilt_angles = np.lib.pad(tilt_angles, padWidthZ, padMode) utils.set_tilt_angles(dataset, tilt_angles) except: # noqa # TODO What exception are we ignoring? pass
def transform_scalars(dataset): """Downsample volume by a factor of 2""" from tomviz import utils import scipy.ndimage import numpy as np array = utils.get_array(dataset) # Downsample the dataset x2 using order 1 spline (linear) # Calculate out array shape def dimensions(array): if array.ndim == 4: zoom = (0.5,0.5,0.5,1) else: zoom = (0.5, 0.5, 0.5) return zoom zoom = dimensions(array) result_shape = utils.zoom_shape(array, zoom) result = np.empty(result_shape, array.dtype, order='F') scipy.ndimage.interpolation.zoom(array, zoom, output=result, order=1, mode='constant', cval=0.0, prefilter=False) # Set the result as the new scalars. utils.set_array(dataset, result) # Update tilt angles if dataset is a tilt series. try: tilt_angles = utils.get_tilt_angles(dataset) result_shape = utils.zoom_shape(tilt_angles, 0.5) result = np.empty(result_shape, array.dtype, order='F') tilt_angles = scipy.ndimage.interpolation.zoom(tilt_angles, 0.5, output=result) utils.set_tilt_angles(dataset, result) except: # noqa # TODO What exception are we ignoring? pass
def transform_scalars(dataset): """3D Reconstruct from a tilt series using Direct Fourier Method""" from tomviz import utils import numpy as np # Get Tilt angles tilt_angles = utils.get_tilt_angles(dataset) data_py = utils.get_array(dataset) if data_py is None: raise RuntimeError("No scalars found!") recon = dfm3(data_py, tilt_angles, np.size(data_py, 0) * 2) print('Reconsruction Complete') # Set the result as the new scalars. utils.set_array(dataset, recon) # Mark dataset as volume utils.mark_as_volume(dataset)
def transform_scalars(dataset): """3D Reconstruct from a tilt series using Direct Fourier Method""" from tomviz import utils import numpy as np # Get Tilt angles tilt_angles = utils.get_tilt_angles(dataset) data_py = utils.get_array(dataset) if data_py is None: raise RuntimeError("No scalars found!") recon = dfm3(data_py,tilt_angles,np.size(data_py,0)*2) print('Reconsruction Complete') # Set the result as the new scalars. utils.set_array(dataset, recon) # Mark dataset as volume utils.mark_as_volume(dataset)
def transform_scalars(dataset): """3D Reconstruct from a tilt series using constraint-based Direct Fourier Method""" from tomviz import utils import numpy as np ###Niter### ###Niter_update_support### ###supportSigma### ###supportThreshold### #percent supportThreshold = supportThreshold / 100.0 nonnegativeVoxels = True tilt_angles = utils.get_tilt_angles(dataset) #Get Tilt angles tilt_images = utils.get_array(dataset) if tilt_images is None: raise RuntimeError("No scalars found!") #Direct Fourier recon without constraints (recon, recon_F) = dfm3(tilt_images, tilt_angles, np.size(tilt_images, 0) * 2) kr_cutoffs = np.linspace(0.05, 0.5, 10) I_data = radial_average( tilt_images, kr_cutoffs ) #average Fourier magnitude of tilt series as a function of kr #Search for solutions that satisfy additional constraints recon = difference_map_update(recon_F, nonnegativeVoxels, I_data, kr_cutoffs, Niter, Niter_update_support, supportSigma, supportThreshold) print('Reconsruction Complete') # Set the result as the new scalars. utils.set_array(dataset, recon) # Mark dataset as volume utils.mark_as_volume(dataset)
def transform_scalars(dataset, resampling_factor=[1, 1, 1]): """Resample dataset""" from tomviz import utils import scipy.ndimage array = utils.get_array(dataset) # Transform the dataset. result = scipy.ndimage.interpolation.zoom(array, resampling_factor) # Set the result as the new scalars. utils.set_array(dataset, result) # Update tilt angles if dataset is a tilt series. if resampling_factor[2] != 1: try: tilt_angles = utils.get_tilt_angles(dataset) tilt_angles = scipy.ndimage.interpolation.zoom( tilt_angles, resampling_factor[2]) utils.set_tilt_angles(dataset, tilt_angles) except: # noqa # TODO What exception are we ignoring? pass
def transform_scalars(dataset, rot_center=0, tune_rot_center=True): """Reconstruct sinograms using the tomopy gridrec algorithm Typically, a data exchange file would be loaded for this reconstruction. This operation will attempt to perform flat-field correction of the raw data using the dark and white background data found in the data exchange file. This operator also requires either the tomviz/tomopy-pipeline docker image, or a python environment with tomopy installed. """ from tomviz import utils import numpy as np import tomopy # Get the current volume as a numpy array. array = utils.get_array(dataset) dark = dataset.dark white = dataset.white angles = utils.get_tilt_angles(dataset) tilt_axis = dataset.tilt_axis # TomoPy wants the tilt axis to be zero, so ensure that is true if tilt_axis == 2: order = [2, 1, 0] array = np.transpose(array, order) if dark is not None and white is not None: dark = np.transpose(dark, order) white = np.transpose(white, order) if angles is not None: # tomopy wants radians theta = np.radians(angles) else: # Assume it is equally spaced between 0 and 180 degrees theta = tomopy.angles(array.shape[0]) # Perform flat-field correction of raw data if white is not None and dark is not None: array = tomopy.normalize(array, white, dark, cutoff=1.4) if rot_center == 0: # Try to find it automatically init = array.shape[2] / 2.0 rot_center = tomopy.find_center(array, theta, init=init, ind=0, tol=0.5) elif tune_rot_center: # Tune the center rot_center = tomopy.find_center(array, theta, init=rot_center, ind=0, tol=0.5) # Calculate -log(array) array = tomopy.minus_log(array) # Remove nan, neg, and inf values array = tomopy.remove_nan(array, val=0.0) array = tomopy.remove_neg(array, val=0.00) array[np.where(array == np.inf)] = 0.00 # Perform the reconstruction array = tomopy.recon(array, theta, center=rot_center, algorithm='gridrec') # Mask each reconstructed slice with a circle. array = tomopy.circ_mask(array, axis=0, ratio=0.95) # Set the transformed array child = utils.make_child_dataset(dataset) utils.mark_as_volume(child) utils.set_array(child, array) return_values = {} return_values['reconstruction'] = child return return_values
def transform_scalars(self, dataset, Niter=10, Nupdates=0): """3D Reconstruct from a tilt series using simple TV minimzation""" self.progress.maximum = 1 # Get Tilt angles tiltAngles = utils.get_tilt_angles(dataset) #remove zero tilt anlges if np.count_nonzero(tiltAngles) < tiltAngles.size: tiltAngles = tiltAngles + 0.001 # Get Tilt Series tiltSeries = utils.get_array(dataset) (Nslice, Nray, Nproj) = tiltSeries.shape # Determine the slices for live updates. Nupdates = calc_Nupdates(Nupdates, Niter) # Generate measurement matrix A = parallelRay(Nray, 1.0, tiltAngles, Nray, 1.0) #A is a sparse matrix recon = np.zeros([Nslice, Nray, Nray], dtype=np.float32, order='F') A = A.tocsr() (Nslice, Nray, Nproj) = tiltSeries.shape (Nrow, Ncol) = A.shape rowInnerProduct = np.zeros(Nrow, dtype=np.float32) row = np.zeros(Ncol, dtype=np.float32) f = np.zeros(Ncol, dtype=np.float32) # Placeholder for 2d image ng = 5 beta = 1.0 r_max = 1.0 gamma_red = 0.8 # Calculate row inner product, preparation for ART recon for j in range(Nrow): row[:] = A[j, :].toarray() rowInnerProduct[j] = np.dot(row, row) self.progress.maximum = Niter * Nslice t0 = time.time() counter = 1 etcMessage = 'Estimated time to complete: n/a' #Create child dataset for recon child = utils.make_child_dataset(dataset) utils.mark_as_volume(child) for i in range(Niter): #main loop recon_temp = recon.copy() #ART recon for s in range(Nslice): # if self.canceled: #In case canceled during ART. return self.progress.message = 'Slice No.%d/%d, Iteration No.%d/%d. '\ % (s + 1, Nslice, i + 1, Niter) + etcMessage if (i == 0): f[:] = 0 elif (i != 0): f[:] = recon[s, :, :].flatten() b = tiltSeries[s, :, :].transpose().flatten() for j in range(Nrow): row[:] = A[j, :].toarray() a = (b[j] - np.dot(row, f)) / rowInnerProduct[j] f = f + row * a * beta recon[s, :, :] = f.reshape((Nray, Nray)) self.progress.value = i*Nslice + s timeLeft = (time.time() - t0) / counter * \ (Nslice * Niter - counter) counter += 1 timeLeftMin, timeLeftSec = divmod(timeLeft, 60) timeLeftHour, timeLeftMin = divmod(timeLeftMin, 60) etcMessage = 'Estimated time to complete: %02d:%02d:%02d' % ( timeLeftHour, timeLeftMin, timeLeftSec) recon[recon < 0] = 0 #Positivity constraint #Update for XX iterations. if Nupdates != 0 and (i + 1) % Nupdates == 0: utils.set_array(child, recon) self.progress.data = child if i != (Niter - 1): self.progress.message = 'Minimizating the Objects TV' #calculate tomogram change due to POCS dPOCS = np.linalg.norm(recon_temp - recon) recon_temp = recon.copy() #3D TV minimization for j in range(ng): R_0 = tv(recon) v = tv_derivative(recon) recon_prime = recon - dPOCS * v recon_prime[recon_prime < 0] = 0 gamma = 1.0 R_f = tv(recon_prime) #Projected Line search while R_f > R_0: gamma = gamma * gamma_red recon_prime = recon - gamma * dPOCS * v recon_prime[recon_prime < 0] = 0 R_f = tv(recon_prime) recon = recon_prime dg = np.linalg.norm(recon - recon_temp) if dg > r_max*dPOCS: recon = r_max*dPOCS/dg*(recon - recon_temp) + recon_temp # One last update of the child data. utils.set_array(child, recon) #add recon to child self.progress.data = child returnValues = {} returnValues["reconstruction"] = child return returnValues
def transform_scalars(self, dataset, Niter=1): """ 3D Reconstruction using Algebraic Reconstruction Technique (ART) """ self.progress.maximum = 1 # Get Tilt angles tiltAngles = utils.get_tilt_angles(dataset) # Get Tilt Series tiltSeries = utils.get_array(dataset) (Nslice, Nray, Nproj) = tiltSeries.shape if tiltSeries is None: raise RuntimeError("No scalars found!") # Generate measurement matrix self.progress.message = 'Generating measurement matrix' A = parallelRay(Nray, 1.0, tiltAngles, Nray, 1.0) #A is a sparse matrix recon = np.empty([Nslice, Nray, Nray], dtype=float, order='F') A = A.todense() (Nslice, Nray, Nproj) = tiltSeries.shape (Nrow, Ncol) = A.shape rowInnerProduct = np.zeros(Nrow) row = np.zeros(Ncol) f = np.zeros(Ncol) # Placeholder for 2d image beta = 1.0 # Calculate row inner product for j in range(Nrow): row[:] = A[j, ].copy() rowInnerProduct[j] = np.dot(row, row) self.progress.maximum = Nslice step = 0 t0 = time.time() etcMessage = 'Estimated time to complete: n/a' counter = 1 for s in range(Nslice): if self.canceled: return f[:] = 0 b = tiltSeries[s, :, :].transpose().flatten() for i in range(Niter): self.progress.message = 'Slice No.%d/%d, iteration No.%d/%d. ' \ % (s + 1, Nslice, i + 1, Niter) + etcMessage for j in range(Nrow): row[:] = A[j, ].copy() row_f_product = np.dot(row, f) a = (b[j] - row_f_product) / rowInnerProduct[j] f = f + row * a * beta timeLeft = (time.time() - t0) / counter * \ (Nslice * Niter - counter) counter += 1 timeLeftMin, timeLeftSec = divmod(timeLeft, 60) timeLeftHour, timeLeftMin = divmod(timeLeftMin, 60) etcMessage = 'Estimated time to complete: %02d:%02d:%02d' % ( timeLeftHour, timeLeftMin, timeLeftSec) recon[s, :, :] = f.reshape((Nray, Nray)) step += 1 self.progress.value = step from vtk import vtkImageData # Set up the output dataset recon_dataset = vtkImageData() recon_dataset.CopyStructure(dataset) utils.set_array(recon_dataset, recon) utils.mark_as_volume(recon_dataset) returnValues = {} returnValues["reconstruction"] = recon_dataset return returnValues
def transform_scalars(self, dataset, Niter=1, Nupdates=0, beta=1.0): """ 3D Reconstruction using Algebraic Reconstruction Technique (ART) """ self.progress.maximum = 1 # Get Tilt angles tiltAngles = utils.get_tilt_angles(dataset) # Get Tilt Series tiltSeries = utils.get_array(dataset) (Nslice, Nray, Nproj) = tiltSeries.shape if tiltSeries is None: raise RuntimeError("No scalars found!") #Check if there's negative values, shift by minimum if true. if np.any(tiltSeries < 0): tiltSeries -= np.amin(tiltSeries) # Determine the slices for live updates. Nupdates = calc_Nupdates(Nupdates, Niter) # Generate measurement matrix self.progress.message = 'Generating measurement matrix' A = parallelRay(Nray, 1.0, tiltAngles, Nray, 1.0) #A is a sparse matrix recon = np.zeros([Nslice, Nray, Nray], dtype=np.float32, order='F') A = A.tocsr() (Nslice, Nray, Nproj) = tiltSeries.shape (Nrow, Ncol) = A.shape rowInnerProduct = np.zeros(Nrow, dtype=np.float32) row = np.zeros(Ncol, dtype=np.float32) f = np.zeros(Ncol, dtype=np.float32) # Placeholder for 2d image beta = 1.0 # Calculate row inner product for j in range(Nrow): row[:] = A[j, :].toarray() rowInnerProduct[j] = np.dot(row, row) self.progress.maximum = Nslice * Niter step = 0 t0 = time.time() etcMessage = 'Estimated time to complete: n/a' #create child for recon child = utils.make_child_dataset(dataset) utils.mark_as_volume(child) counter = 1 for i in range(Niter): for s in range(Nslice): if self.canceled: return self.progress.message = 'Iteration No.%d/%d,Slice No.%d/%d.' % ( i + 1, Niter, s + 1, Nslice) + etcMessage #Initialize slice as zeros on first iteration, #or vectorize the slice for the next iter. if (i == 0): f[:] = 0 elif (i != 0): f[:] = recon[s, :, :].flatten() b = tiltSeries[s, :, :].transpose().flatten() for j in range(Nrow): row[:] = A[j, :].toarray() a = (b[j] - np.dot(row, f)) / rowInnerProduct[j] f = f + row * a * beta recon[s, :, :] = f.reshape((Nray, Nray)) # Give 4 updates for first iteration. if Nupdates != 0 and i == 0 and (s + 1) % (Nslice // 4) == 0: utils.set_array(child, recon) self.progress.data = child step += 1 self.progress.value = step timeLeft = (time.time() - t0) / counter * \ (Nslice * Niter - counter) counter += 1 timeLeftMin, timeLeftSec = divmod(timeLeft, 60) timeLeftHour, timeLeftMin = divmod(timeLeftMin, 60) etcMessage = 'Estimated time to complete: %02d:%02d:%02d' % ( timeLeftHour, timeLeftMin, timeLeftSec) recon[recon < 0] = 0 #Positivity constraint #Update for XX iterations. if Nupdates != 0 and (i + 1) % Nupdates == 0: utils.set_array(child, recon) self.progress.data = child # One last update of the child data. utils.set_array(child, recon) #add recon to child self.progress.data = child returnValues = {} returnValues["reconstruction"] = child return returnValues
def transform_scalars(self, dataset, Niter=None, Niter_update_support=None, supportSigma=None, supportThreshold=None): """ 3D Reconstruct from a tilt series using constraint-based Direct Fourier Method """ self.progress.maximum = 1 from tomviz import utils import numpy as np supportThreshold = supportThreshold / 100.0 nonnegativeVoxels = True tiltAngles = utils.get_tilt_angles(dataset) #Get Tilt angles tiltSeries = utils.get_array(dataset) if tiltSeries is None: raise RuntimeError("No scalars found!") self.progress.message = 'Initialization' #Direct Fourier recon without constraints (recon, recon_F) \ = dfm3(tiltSeries, tiltAngles, np.size(tiltSeries, 1) * 2) kr_cutoffs = np.linspace(0.05, 0.5, 10) #average Fourier magnitude of tilt series as a function of kr I_data = radial_average(tiltSeries, kr_cutoffs) (Nx, Ny, Nz) = recon_F.shape #Note: Nz = np.int(Ny/2+1) Ntot = Nx * Ny * Ny f = pyfftw.n_byte_align_empty((Nx, Ny, Nz), 16, dtype='complex128') r = pyfftw.n_byte_align_empty((Nx, Ny, Ny), 16, dtype='float64') fft_forward = pyfftw.FFTW(r, f, axes=(0, 1, 2)) fft_inverse = pyfftw.FFTW(f, r, direction='FFTW_BACKWARD', axes=(0, 1, 2)) kx = np.fft.fftfreq(Nx) ky = np.fft.fftfreq(Ny) kz = ky[0:Nz] kX, kY, kZ = np.meshgrid(ky, kx, kz) kR = np.sqrt(kY**2 + kX**2 + kZ**2) sigma = 0.5 * supportSigma G = np.exp(-kR**2 / (2 * sigma**2)) #create initial support using sw f = recon_F * G fft_inverse.update_arrays(f, r) fft_inverse.execute() cutoff = np.amax(r) * supportThreshold support = r >= cutoff recon_F[kR > kr_cutoffs[-1]] = 0 x = np.random.rand(Nx, Ny, Ny) #initial solution self.progress.maximum = Niter step = 0 t0 = time.time() counter = 1 etcMessage = 'Estimated time to complete: n/a' for i in range(Niter): if self.canceled: return self.progress.message = 'Iteration No.%d/%d. ' % ( i + 1, Niter) + etcMessage #image space projection y1 = x.copy() if nonnegativeVoxels: y1[y1 < 0] = 0 #non-negative constraint y1[np.logical_not(support)] = 0 #support constraint #Fourier space projection y2 = 2 * y1 - x r = y2.copy() fft_forward.update_arrays(r, f) fft_forward.execute() f[kR > kr_cutoffs[-1]] = 0 #apply low pass filter f[recon_F != 0] = recon_F[recon_F != 0] #data constraint #Fourier magnitude constraint #leave the inner shell unchanged for j in range(1, kr_cutoffs.size): shell = np.logical_and(kR > kr_cutoffs[j - 1], kR <= kr_cutoffs[j]) shell[recon_F != 0] = False I = np.sum(np.absolute(f[shell])) if I != 0: I = I / np.sum(shell) # lower magnitude for high frequency information to reduce # artifacts f[shell] = f[shell] / I * I_data[j] * 0.5 fft_inverse.update_arrays(f, r) fft_inverse.execute() y2 = r.copy() / Ntot #update x = x + y2 - y1 #update support if (i < Niter and np.mod(i, Niter_update_support) == 0): recon[:] = (y2 + y1) / 2 r = recon.copy() fft_forward.update_arrays(r, f) fft_forward.execute() f = f * G fft_inverse.update_arrays(f, r) fft_inverse.execute() cutoff = np.amax(r) * supportThreshold support = r >= cutoff step += 1 self.progress.value = step timeLeft = (time.time() - t0) / counter * (Niter - counter) counter += 1 timeLeftMin, timeLeftSec = divmod(timeLeft, 60) timeLeftHour, timeLeftMin = divmod(timeLeftMin, 60) etcMessage = 'Estimated time to complete: %02d:%02d:%02d' % ( timeLeftHour, timeLeftMin, timeLeftSec) recon[:] = (y2 + y1) / 2 recon[:] = np.fft.fftshift(recon) from vtk import vtkImageData recon_dataset = vtkImageData() recon_dataset.CopyStructure(dataset) utils.set_array(recon_dataset, recon) utils.mark_as_volume(recon_dataset) returnValues = {} returnValues["reconstruction"] = recon_dataset return returnValues
def transform_scalars(self, dataset, Niter=10, stepSize=0.0001, updateMethodIndex=0, Nupdates=0): """ 3D Reconstruct from a tilt series using Simultaneous Iterative Reconstruction Techniques (SIRT)""" self.progress.maximum = 1 update_methods = ('landweber', 'cimmino', 'component averaging') #reference """L. Landweber, Amer. J. Math., 73 (1951), pp. 615–624""" """G. Cimmino, La Ric. Sci., XVI, Ser. II, Anno IX, 1 (1938), pp. 326–333 """ """Y. Censor et al, Parallel Comput., 27 (2001), pp. 777–808""" # Get Tilt angles tiltAngles = utils.get_tilt_angles(dataset) #remove zero tilt anlges if np.count_nonzero(tiltAngles) < tiltAngles.size: tiltAngles = tiltAngles + 0.001 # Get Tilt Series tiltSeries = utils.get_array(dataset) (Nslice, Nray, Nproj) = tiltSeries.shape #Check if there's negative values, shift by minimum if true. if np.any(tiltSeries < 0): tiltSeries -= np.amin(tiltSeries) if tiltSeries is None: raise RuntimeError("No scalars found!") # Determine slice for live updates Nupdates = calc_Nupdates(Nupdates, Niter) # Generate measurement matrix self.progress.message = 'Generating measurement matrix' A = parallelRay(Nray, 1.0, tiltAngles, Nray, 1.0) #A is a sparse matrix recon = np.zeros([Nslice, Nray, Nray], dtype=np.float32, order='F') self.progress.maximum = Nslice * Niter + 1 step = 0 #create a reconstruction object r = SIRT(A, update_methods[updateMethodIndex], Nslice) r.initialize() step += 1 self.progress.value = step t0 = time.time() counter = 1 etcMessage = 'Estimated time to complete: n/a' #create child for recon child = utils.make_child_dataset(dataset) utils.mark_as_volume(child) for i in range(Niter): for s in range(Nslice): if self.canceled: return self.progress.message = 'Iteration No.%d/%d,Slice No.%d/%d.' % ( i + 1, Niter, s + 1, Nslice) + etcMessage b = tiltSeries[s, :, :].transpose().flatten() recon_slice = recon[s, :, :].flatten() recon[s, :, :] = r.recon2(b, recon_slice, stepSize, s).reshape( (Nray, Nray)) step += 1 self.progress.value = step timeLeft = (time.time() - t0) / counter * (Nslice * Niter - counter) counter += 1 timeLeftMin, timeLeftSec = divmod(timeLeft, 60) timeLeftHour, timeLeftMin = divmod(timeLeftMin, 60) etcMessage = 'Estimated time to complete: %02d:%02d:%02d' % ( timeLeftHour, timeLeftMin, timeLeftSec) # Give 4 updates for first iteration. if Nupdates != 0 and i == 0 and (s + 1) % (Nslice // 4) == 0: utils.set_array(child, recon) self.progress.data = child #Positivity constraint. recon[recon < 0] = 0 #Update at the end of each iteration. if Nupdates != 0 and (i + 1) % Nupdates == 0: utils.set_array(child, recon) self.progress.data = child # One last update of the child data. utils.set_array(child, recon) #add recon to child self.progress.data = child returnValues = {} returnValues["reconstruction"] = child return returnValues
def tilt_angles(self): return utils.get_tilt_angles(self._data_object)
def transform_scalars(self, dataset): """3D Reconstruct from a tilt series using Direct Fourier Method""" self.progress.maximum = 1 # Get Tilt angles tiltAngles = utils.get_tilt_angles(dataset) tiltSeries = utils.get_array(dataset) if tiltSeries is None: raise RuntimeError("No scalars found!") tiltSeries = np.double(tiltSeries) (Nx, Ny, Nproj) = tiltSeries.shape Npad = Ny * 2 tiltAngles = np.double(tiltAngles) pad_pre = int(np.ceil((Npad - Ny) / 2.0)) pad_post = int(np.floor((Npad - Ny) / 2.0)) # Initialization self.progress.message = 'Initialization' Nz = Ny w = np.zeros((Nx, Ny, Nz // 2 + 1)) #store weighting factors v = pyfftw.empty_aligned( (Nx, Ny, Nz // 2 + 1), dtype='complex64', n=16) p = pyfftw.empty_aligned((Nx, Npad), dtype='float32', n=16) pF = pyfftw.empty_aligned( (Nx, Npad // 2 + 1), dtype='complex64', n=16) p_fftw_object = pyfftw.FFTW(p, pF, axes=(0, 1)) dk = np.double(Ny) / np.double(Npad) self.progress.maximum = Nproj + 1 step = 0 t0 = time.time() etcMessage = 'Estimated time to complete: n/a' counter = 1 for a in range(Nproj): if self.canceled: return self.progress.message = 'Tilt image No.%d/%d. ' % ( a + 1, Nproj) + etcMessage ang = tiltAngles[a] * np.pi / 180 projection = tiltSeries[:, :, a] #2D projection image p = np.lib.pad(projection, ((0, 0), (pad_pre, pad_post)), 'constant', constant_values=(0, 0)) #pad zeros p = np.float32(np.fft.ifftshift(p)) p_fftw_object.update_arrays(p, pF) p_fftw_object() p = None #Garbage collector (gc) if ang < 0: pF = np.conj(pF) pF[1:, :] = np.flipud(pF[1:, :]) ang = np.pi + ang # Bilinear extrapolation for i in range(0, np.int(np.ceil(Npad / 2)) + 1): ky = i * dk #kz = 0 ky_new = np.cos(ang) * ky #new coord. after rotation kz_new = np.sin(ang) * ky sy = abs(np.floor(ky_new) - ky_new) #calculate weights sz = abs(np.floor(kz_new) - kz_new) for b in range(1, 5): #bilinear extrapolation pz, py, weight = bilinear(kz_new, ky_new, sz, sy, Ny, b) if (py >= 0 and py < Ny and pz >= 0 and pz < Nz / 2 + 1): w[:, py, pz] = w[:, py, pz] + weight v[:, py, pz] = v[:, py, pz] + \ weight * pF[:, i] step += 1 self.progress.value = step timeLeft = (time.time() - t0) / counter * (Nproj - counter) counter += 1 timeLeftMin, timeLeftSec = divmod(timeLeft, 60) timeLeftHour, timeLeftMin = divmod(timeLeftMin, 60) etcMessage = 'Estimated time to complete: %02d:%02d:%02d' % ( timeLeftHour, timeLeftMin, timeLeftSec) p = pF = None #gc self.progress.message = 'Inverse Fourier transform' v_temp = v.copy() recon = pyfftw.empty_aligned( (Nx, Ny, Nz), dtype='float32', order='F', n=16) recon_fftw_object = pyfftw.FFTW( v_temp, recon, direction='FFTW_BACKWARD', axes=(0, 1, 2)) v[w != 0] = v[w != 0] / w[w != 0] recon_fftw_object.update_arrays(v, recon) v = v_temp = [] #gc recon_fftw_object() recon[:] = np.fft.fftshift(recon) step += 1 self.progress.value = step self.progress.message = 'Passing data to Tomviz' from vtkmodules.vtkCommonDataModel import vtkImageData recon_dataset = vtkImageData() recon_dataset.CopyStructure(dataset) utils.set_array(recon_dataset, recon) utils.mark_as_volume(recon_dataset) recon = None #gc returnValues = {} returnValues["reconstruction"] = recon_dataset return returnValues
def transform_scalars(self, dataset, Niter=None, stepSize=None, updateMethodIndex=None): """ 3D Reconstruct from a tilt series using Simultaneous Iterative Reconstruction Techniques (SIRT)""" self.progress.maximum = 1 update_methods = ('landweber', 'cimmino', 'component averaging') #reference """L. Landweber, Amer. J. Math., 73 (1951), pp. 615–624""" """G. Cimmino, La Ric. Sci., XVI, Ser. II, Anno IX, 1 (1938), pp. 326–333 """ """Y. Censor et al, Parallel Comput., 27 (2001), pp. 777–808""" # Get Tilt angles tiltAngles = utils.get_tilt_angles(dataset) #remove zero tilt anlges if np.count_nonzero(tiltAngles) < tiltAngles.size: tiltAngles = tiltAngles + 0.001 # Get Tilt Series tiltSeries = utils.get_array(dataset) (Nslice, Nray, Nproj) = tiltSeries.shape if tiltSeries is None: raise RuntimeError("No scalars found!") # Generate measurement matrix self.progress.message = 'Generating measurement matrix' A = parallelRay(Nray, 1.0, tiltAngles, Nray, 1.0) #A is a sparse matrix recon = np.empty([Nslice, Nray, Nray], dtype=float, order='F') self.progress.maximum = Nslice + 1 step = 0 #create a reconstruction object r = SIRT(A, update_methods[updateMethodIndex]) r.initialize() step += 1 self.progress.value = step t0 = time.time() counter = 1 etcMessage = 'Estimated time to complete: n/a' for s in range(Nslice): if self.canceled: return self.progress.message = 'Slice No.%d/%d. ' % ( s + 1, Nslice) + etcMessage b = tiltSeries[s, :, :].transpose().flatten() recon[s, :, :] = r.recon2(b, Niter, stepSize).reshape((Nray, Nray)) step += 1 self.progress.value = step timeLeft = (time.time() - t0) / counter * (Nslice - counter) counter += 1 timeLeftMin, timeLeftSec = divmod(timeLeft, 60) timeLeftHour, timeLeftMin = divmod(timeLeftMin, 60) etcMessage = 'Estimated time to complete: %02d:%02d:%02d' % ( timeLeftHour, timeLeftMin, timeLeftSec) from vtk import vtkImageData recon_dataset = vtkImageData() recon_dataset.CopyStructure(dataset) utils.set_array(recon_dataset, recon) utils.mark_as_volume(recon_dataset) returnValues = {} returnValues["reconstruction"] = recon_dataset return returnValues
def transform_scalars(self, dataset, Niter=1): """ 3D Reconstruction using Algebraic Reconstruction Technique (ART) """ self.progress.maximum = 1 # Get Tilt angles tiltAngles = utils.get_tilt_angles(dataset) # Get Tilt Series tiltSeries = utils.get_array(dataset) (Nslice, Nray, Nproj) = tiltSeries.shape if tiltSeries is None: raise RuntimeError("No scalars found!") # Generate measurement matrix self.progress.message = 'Generating measurement matrix' A = parallelRay(Nray, 1.0, tiltAngles, Nray, 1.0) #A is a sparse matrix recon = np.zeros((Nslice, Nray, Nray)) A = A.todense() (Nslice, Nray, Nproj) = tiltSeries.shape (Nrow, Ncol) = A.shape rowInnerProduct = np.zeros(Nrow) row = np.zeros(Ncol) f = np.zeros(Ncol) # Placeholder for 2d image beta = 1.0 # Calculate row inner product for j in range(Nrow): row[:] = A[j, ].copy() rowInnerProduct[j] = np.dot(row, row) self.progress.maximum = Nslice step = 0 for s in range(Nslice): if self.canceled: return f[:] = 0 b = tiltSeries[s, :, :].transpose().flatten() for i in range(Niter): self.progress.message = 'Slice No.%d/%d, iteration No.%d/%d' % ( s + 1, Nslice, i + 1, Niter) for j in range(Nrow): row[:] = A[j, ].copy() row_f_product = np.dot(row, f) a = (b[j] - row_f_product) / rowInnerProduct[j] f = f + row * a * beta recon[s, :, :] = f.reshape((Nray, Nray)) step += 1 self.progress.value = step # Set the result as the new scalars. utils.set_array(dataset, recon) # Mark dataset as volume utils.mark_as_volume(dataset)
def transform_scalars(self, dataset, Nrecon=None, filter=None, interp=None): """ 3D Reconstruct from a tilt series using Weighted Back-projection Method """ self.progress.maximum = 1 from tomviz import utils interpolation_methods = ('linear', 'nearest', 'spline', 'cubic') filter_methods = ('none', 'ramp', 'shepp-logan', 'cosine', 'hamming', 'hann') # Get Tilt angles tilt_angles = utils.get_tilt_angles(dataset) tiltSeries = utils.get_array(dataset) if tiltSeries is None: raise RuntimeError("No scalars found!") Nslice = tiltSeries.shape[0] self.progress.maximum = Nslice step = 0 recon = np.empty([Nslice, Nrecon, Nrecon], dtype=float, order='F') t0 = time.time() counter = 1 etcMessage = 'Estimated time to complete: n/a' child = utils.make_child_dataset(dataset) #create child for recon utils.mark_as_volume(child) for i in range(Nslice): if self.canceled: return self.progress.message = 'Slice No.%d/%d. ' % (i + 1, Nslice) + etcMessage recon[i, :, :] = wbp2(tiltSeries[i, :, :], tilt_angles, Nrecon, filter_methods[filter], interpolation_methods[interp]) step += 1 self.progress.value = step timeLeft = (time.time() - t0) / counter * (Nslice - counter) counter += 1 timeLeftMin, timeLeftSec = divmod(timeLeft, 60) timeLeftHour, timeLeftMin = divmod(timeLeftMin, 60) etcMessage = 'Estimated time to complete: %02d:%02d:%02d' % ( timeLeftHour, timeLeftMin, timeLeftSec) # Update only once every so many steps if (i + 1) % 40 == 0: utils.set_array(child, recon) #add recon to child # This copies data to the main thread self.progress.data = child # One last update of the child data. utils.set_array(child, recon) #add recon to child self.progress.data = child returnValues = {} returnValues["reconstruction"] = child return returnValues
def transform_scalars(self, dataset): """Automatically align tilt images by cross-correlation""" self.progress.maximum = 1 tiltSeries = utils.get_array(dataset).astype(float) tiltAngles = utils.get_tilt_angles(dataset) # determine reference image index zeroDegreeTiltImage = None if tiltAngles is not None: zeroDegreeTiltImage = np.where(tiltAngles == 0)[0] if zeroDegreeTiltImage: referenceIndex = zeroDegreeTiltImage[0] else: referenceIndex = tiltSeries.shape[2] // 2 # create Fourier space filter filterCutoff = 4 (Ny, Nx, Nproj) = tiltSeries.shape ky = np.fft.fftfreq(Ny) kx = np.fft.fftfreq(Nx) [kX, kY] = np.meshgrid(kx, ky) kR = np.sqrt(kX**2 + kY**2) kFilter = (kR <= (0.5 / filterCutoff)) * \ np.sin(2 * filterCutoff * np.pi * kR)**2 # create real sapce filter to remove edge discontinuities y = np.linspace(1, Ny, Ny) x = np.linspace(1, Nx, Nx) [X, Y] = np.meshgrid(x, y) rFilter = (np.sin(np.pi * X / Nx) * np.sin(np.pi * Y / Ny)) ** 2 self.progress.maximum = tiltSeries.shape[2] - 1 step = 1 offsets = np.zeros((tiltSeries.shape[2], 2)) for i in range(referenceIndex, Nproj - 1): if self.canceled: return self.progress.message = 'Processing tilt image No.%d/%d' % ( step, Nproj) offsets[i + 1, :], tiltSeries[:, :, i + 1] = crossCorrelationAlign( tiltSeries[:, :, i + 1], tiltSeries[:, :, i], rFilter, kFilter) step += 1 self.progress.value = step for i in range(referenceIndex, 0, -1): if self.canceled: return self.progress.message = 'Processing tilt image No.%d/%d' % ( step, Nproj) offsets[i - 1, :], tiltSeries[:, :, i - 1] = crossCorrelationAlign( tiltSeries[:, :, i - 1], tiltSeries[:, :, i], rFilter, kFilter) step += 1 self.progress.value = step utils.set_array(dataset, tiltSeries) # Assign Negative Shifts when Shift > N/2. indices_X = np.where(offsets[:, 0] > tiltSeries.shape[0] / 2) offsets[indices_X, 0] -= tiltSeries.shape[0] indices_Y = np.where(offsets[:, 1] > tiltSeries.shape[1] / 2) offsets[indices_Y, 1] -= tiltSeries.shape[1] # Create a spreadsheet data set from table data column_names = ["X Offset", "Y Offset"] offsetsTable = utils.make_spreadsheet(column_names, offsets) # Set up dictionary to return operator results returnValues = {} returnValues["alignments"] = offsetsTable return returnValues
def transform_scalars(self, dataset, Nrecon=None, filter=None, interp=None, Nupdates=None): """ 3D Reconstruct from a tilt series using Weighted Back-projection Method """ self.progress.maximum = 1 from tomviz import utils interpolation_methods = ('linear', 'nearest', 'spline', 'cubic') filter_methods = ('none', 'ramp', 'shepp-logan', 'cosine', 'hamming', 'hann') # Get Tilt angles tilt_angles = utils.get_tilt_angles(dataset) tiltSeries = utils.get_array(dataset) if tiltSeries is None: raise RuntimeError("No scalars found!") Nslice = tiltSeries.shape[0] self.progress.maximum = Nslice step = 0 recon = np.empty([Nslice, Nrecon, Nrecon], dtype=np.float32, order='F') t0 = time.time() counter = 1 etcMessage = 'Estimated time to complete: n/a' child = utils.make_child_dataset(dataset) #create child for recon utils.mark_as_volume(child) for i in range(Nslice): if self.canceled: return self.progress.message = 'Slice No.%d/%d. ' % ( i + 1, Nslice) + etcMessage recon[i, :, :] = wbp2(tiltSeries[i, :, :], tilt_angles, Nrecon, filter_methods[filter], interpolation_methods[interp]) step += 1 self.progress.value = step timeLeft = (time.time() - t0) / counter * (Nslice - counter) counter += 1 timeLeftMin, timeLeftSec = divmod(timeLeft, 60) timeLeftHour, timeLeftMin = divmod(timeLeftMin, 60) etcMessage = 'Estimated time to complete: %02d:%02d:%02d' % ( timeLeftHour, timeLeftMin, timeLeftSec) # Update only once every so many steps if Nupdates != 0 and (i + 1) % (Nslice//Nupdates) == 0: utils.set_array(child, recon) #add recon to child # This copies data to the main thread self.progress.data = child # One last update of the child data. utils.set_array(child, recon) #add recon to child self.progress.data = child returnValues = {} returnValues["reconstruction"] = child return returnValues
def transform_scalars(self, dataset): """3D Reconstruct from a tilt series using Direct Fourier Method""" self.progress.maximum = 1 # Get Tilt angles tiltAngles = utils.get_tilt_angles(dataset) tiltSeries = utils.get_array(dataset) if tiltSeries is None: raise RuntimeError("No scalars found!") tiltSeries = np.double(tiltSeries) (Nx, Ny, Nproj) = tiltSeries.shape Npad = Ny * 2 tiltAngles = np.double(tiltAngles) pad_pre = int(np.ceil((Npad - Ny) / 2.0)) pad_post = int(np.floor((Npad - Ny) / 2.0)) # Initialization self.progress.message = 'Initialization' Nz = Ny w = np.zeros((Nx, Ny, Nz // 2 + 1)) #store weighting factors v = pyfftw.empty_aligned( (Nx, Ny, Nz // 2 + 1), dtype='complex64', n=16) p = pyfftw.empty_aligned((Nx, Npad), dtype='float32', n=16) pF = pyfftw.empty_aligned( (Nx, Npad // 2 + 1), dtype='complex64', n=16) p_fftw_object = pyfftw.FFTW(p, pF, axes=(0, 1)) dk = np.double(Ny) / np.double(Npad) self.progress.maximum = Nproj + 1 step = 0 t0 = time.time() etcMessage = 'Estimated time to complete: n/a' counter = 1 for a in range(Nproj): if self.canceled: return self.progress.message = 'Tilt image No.%d/%d. ' % ( a + 1, Nproj) + etcMessage ang = tiltAngles[a] * np.pi / 180 projection = tiltSeries[:, :, a] #2D projection image p = np.lib.pad(projection, ((0, 0), (pad_pre, pad_post)), 'constant', constant_values=(0, 0)) #pad zeros p = np.float32(np.fft.ifftshift(p)) p_fftw_object.update_arrays(p, pF) p_fftw_object() p = None #Garbage collector (gc) if ang < 0: pF = np.conj(pF) pF[1:, :] = np.flipud(pF[1:, :]) ang = np.pi + ang # Bilinear extrapolation for i in range(0, np.int(np.ceil(Npad / 2)) + 1): ky = i * dk #kz = 0 ky_new = np.cos(ang) * ky #new coord. after rotation kz_new = np.sin(ang) * ky sy = abs(np.floor(ky_new) - ky_new) #calculate weights sz = abs(np.floor(kz_new) - kz_new) for b in range(1, 5): #bilinear extrapolation pz, py, weight = bilinear(kz_new, ky_new, sz, sy, Ny, b) if (py >= 0 and py < Ny and pz >= 0 and pz < np.floor( Nz / 2 + 1 )): w[:, py, pz] = w[:, py, pz] + weight v[:, py, pz] = v[:, py, pz] + \ weight * pF[:, i] step += 1 self.progress.value = step timeLeft = (time.time() - t0) / counter * (Nproj - counter) counter += 1 timeLeftMin, timeLeftSec = divmod(timeLeft, 60) timeLeftHour, timeLeftMin = divmod(timeLeftMin, 60) etcMessage = 'Estimated time to complete: %02d:%02d:%02d' % ( timeLeftHour, timeLeftMin, timeLeftSec) p = pF = None #gc self.progress.message = 'Inverse Fourier transform' v_temp = v.copy() recon = pyfftw.empty_aligned( (Nx, Ny, Nz), dtype='float32', order='F', n=16) recon_fftw_object = pyfftw.FFTW( v_temp, recon, direction='FFTW_BACKWARD', axes=(0, 1, 2)) v[w != 0] = v[w != 0] / w[w != 0] recon_fftw_object.update_arrays(v, recon) v = v_temp = [] #gc recon_fftw_object() recon[:] = np.fft.fftshift(recon) step += 1 self.progress.value = step self.progress.message = 'Passing data to Tomviz' from vtkmodules.vtkCommonDataModel import vtkImageData recon_dataset = vtkImageData() recon_dataset.CopyStructure(dataset) utils.set_array(recon_dataset, recon) utils.mark_as_volume(recon_dataset) recon = None #gc returnValues = {} returnValues["reconstruction"] = recon_dataset return returnValues
def transform_scalars(self, dataset, Niter=10, stepSize=0.0001, updateMethodIndex=0, Nupdates=0): """ 3D Reconstruct from a tilt series using Simultaneous Iterative Reconstruction Techniques (SIRT)""" self.progress.maximum = 1 update_methods = ('landweber', 'cimmino', 'component averaging') #reference """L. Landweber, Amer. J. Math., 73 (1951), pp. 615–624""" """G. Cimmino, La Ric. Sci., XVI, Ser. II, Anno IX, 1 (1938), pp. 326–333 """ """Y. Censor et al, Parallel Comput., 27 (2001), pp. 777–808""" # Get Tilt angles tiltAngles = utils.get_tilt_angles(dataset) #remove zero tilt anlges if np.count_nonzero(tiltAngles) < tiltAngles.size: tiltAngles = tiltAngles + 0.001 # Get Tilt Series tiltSeries = utils.get_array(dataset) (Nslice, Nray, Nproj) = tiltSeries.shape #Check if there's negative values, shift by minimum if true. if np.any(tiltSeries < 0): tiltSeries -= np.amin(tiltSeries) if tiltSeries is None: raise RuntimeError("No scalars found!") # Determine slice for live updates Nupdates = calc_Nupdates(Nupdates, Niter) # Generate measurement matrix self.progress.message = 'Generating measurement matrix' A = parallelRay(Nray, 1.0, tiltAngles, Nray, 1.0) #A is a sparse matrix recon = np.zeros([Nslice, Nray, Nray], dtype=np.float32, order='F') self.progress.maximum = Nslice*Niter + 1 step = 0 #create a reconstruction object r = SIRT(A, update_methods[updateMethodIndex], Nslice) r.initialize() step += 1 self.progress.value = step t0 = time.time() counter = 1 etcMessage = 'Estimated time to complete: n/a' #create child for recon child = utils.make_child_dataset(dataset) utils.mark_as_volume(child) for i in range(Niter): for s in range(Nslice): if self.canceled: return self.progress.message = 'Iteration No.%d/%d,Slice No.%d/%d.' % ( i + 1, Niter, s + 1, Nslice) + etcMessage b = tiltSeries[s, :, :].transpose().flatten() recon_slice = recon[s, :, :].flatten() recon[s, :, :] = r.recon2(b, recon_slice, stepSize, s).reshape((Nray, Nray)) step += 1 self.progress.value = step timeLeft = (time.time() - t0) / counter * (Nslice*Niter - counter) counter += 1 timeLeftMin, timeLeftSec = divmod(timeLeft, 60) timeLeftHour, timeLeftMin = divmod(timeLeftMin, 60) etcMessage = 'Estimated time to complete: %02d:%02d:%02d' % ( timeLeftHour, timeLeftMin, timeLeftSec) # Give 4 updates for first iteration. if Nupdates != 0 and i == 0 and (s + 1) % (Nslice//4) == 0: utils.set_array(child, recon) self.progress.data = child #Positivity constraint. recon[recon < 0] = 0 #Update at the end of each iteration. if Nupdates != 0 and (i + 1) % Nupdates == 0: utils.set_array(child, recon) self.progress.data = child # One last update of the child data. utils.set_array(child, recon) #add recon to child self.progress.data = child returnValues = {} returnValues["reconstruction"] = child return returnValues
def transform_scalars(self, dataset, Niter=None, Niter_update_support=None, supportSigma=None, supportThreshold=None): """ 3D Reconstruct from a tilt series using constraint-based Direct Fourier Method """ self.progress.maximum = 1 from tomviz import utils import numpy as np supportThreshold = supportThreshold / 100.0 nonnegativeVoxels = True tiltAngles = utils.get_tilt_angles(dataset) #Get Tilt angles tiltSeries = utils.get_array(dataset) if tiltSeries is None: raise RuntimeError("No scalars found!") self.progress.message = 'Initialization' #Direct Fourier recon without constraints (recon, recon_F) \ = dfm3(tiltSeries, tiltAngles, np.size(tiltSeries, 1) * 2) kr_cutoffs = np.linspace(0.05, 0.5, 10) #average Fourier magnitude of tilt series as a function of kr I_data = radial_average(tiltSeries, kr_cutoffs) (Nx, Ny, Nz) = recon_F.shape #Note: Nz = np.int(Ny/2+1) Ntot = Nx * Ny * Ny f = pyfftw.n_byte_align_empty((Nx, Ny, Nz), 16, dtype='complex128') r = pyfftw.n_byte_align_empty((Nx, Ny, Ny), 16, dtype='float64') fft_forward = pyfftw.FFTW(r, f, axes=(0, 1, 2)) fft_inverse = pyfftw.FFTW( f, r, direction='FFTW_BACKWARD', axes=(0, 1, 2)) kx = np.fft.fftfreq(Nx) ky = np.fft.fftfreq(Ny) kz = ky[0:Nz] kX, kY, kZ = np.meshgrid(ky, kx, kz) kR = np.sqrt(kY**2 + kX**2 + kZ**2) sigma = 0.5 * supportSigma G = np.exp(-kR**2 / (2 * sigma**2)) #create initial support using sw f = recon_F * G fft_inverse.update_arrays(f, r) fft_inverse.execute() cutoff = np.amax(r) * supportThreshold support = r >= cutoff recon_F[kR > kr_cutoffs[-1]] = 0 x = np.random.rand(Nx, Ny, Ny) #initial solution self.progress.maximum = Niter step = 0 t0 = time.time() counter = 1 etcMessage = 'Estimated time to complete: n/a' for i in range(Niter): if self.canceled: return self.progress.message = 'Iteration No.%d/%d. ' % ( i + 1, Niter) + etcMessage #image space projection y1 = x.copy() if nonnegativeVoxels: y1[y1 < 0] = 0 #non-negative constraint y1[np.logical_not(support)] = 0 #support constraint #Fourier space projection y2 = 2 * y1 - x r = y2.copy() fft_forward.update_arrays(r, f) fft_forward.execute() f[kR > kr_cutoffs[-1]] = 0 #apply low pass filter f[recon_F != 0] = recon_F[recon_F != 0] #data constraint #Fourier magnitude constraint #leave the inner shell unchanged for j in range(1, kr_cutoffs.size): shell = np.logical_and( kR > kr_cutoffs[j - 1], kR <= kr_cutoffs[j]) shell[recon_F != 0] = False I = np.sum(np.absolute(f[shell])) if I != 0: I = I / np.sum(shell) # lower magnitude for high frequency information to reduce # artifacts f[shell] = f[shell] / I * I_data[j] * 0.5 fft_inverse.update_arrays(f, r) fft_inverse.execute() y2 = r.copy() / Ntot #update x = x + y2 - y1 #update support if (i < Niter and np.mod(i, Niter_update_support) == 0): recon[:] = (y2 + y1) / 2 r = recon.copy() fft_forward.update_arrays(r, f) fft_forward.execute() f = f * G fft_inverse.update_arrays(f, r) fft_inverse.execute() cutoff = np.amax(r) * supportThreshold support = r >= cutoff step += 1 self.progress.value = step timeLeft = (time.time() - t0) / counter * (Niter - counter) counter += 1 timeLeftMin, timeLeftSec = divmod(timeLeft, 60) timeLeftHour, timeLeftMin = divmod(timeLeftMin, 60) etcMessage = 'Estimated time to complete: %02d:%02d:%02d' % ( timeLeftHour, timeLeftMin, timeLeftSec) recon[:] = (y2 + y1) / 2 recon[:] = np.fft.fftshift(recon) # Set the result as the new scalars. utils.set_array(dataset, recon) # Mark dataset as volume utils.mark_as_volume(dataset)
def transform_scalars(self, dataset): """3D Reconstruct from a tilt series using Direct Fourier Method""" self.progress.maximum = 1 from tomviz import utils import numpy as np # Get Tilt angles tiltAngles = utils.get_tilt_angles(dataset) tiltSeries = utils.get_array(dataset) if tiltSeries is None: raise RuntimeError("No scalars found!") Npad = np.size(tiltSeries, 0) * 2 tiltSeries = np.double(tiltSeries) (Nx, Ny, Nproj) = tiltSeries.shape tiltAngles = np.double(tiltAngles) pad_pre = int(np.ceil((Npad - Ny) / 2.0)) pad_post = int(np.floor((Npad - Ny) / 2.0)) # Initialization self.progress.message = 'Initialization' Nz = Ny w = np.zeros((Nx, Ny, Nz // 2 + 1)) #store weighting factors v = pyfftw.n_byte_align_empty((Nx, Ny, Nz // 2 + 1), 16, dtype='complex128') v = np.zeros(v.shape) + 1j * np.zeros(v.shape) recon = pyfftw.n_byte_align_empty((Nx, Ny, Nz), 16, dtype='float64') recon_fftw_object = pyfftw.FFTW(v, recon, direction='FFTW_BACKWARD', axes=(0, 1, 2)) p = pyfftw.n_byte_align_empty((Nx, Npad), 16, dtype='float64') pF = pyfftw.n_byte_align_empty((Nx, Npad // 2 + 1), 16, dtype='complex128') p_fftw_object = pyfftw.FFTW(p, pF, axes=(0, 1)) dk = np.double(Ny) / np.double(Npad) self.progress.maximum = Nproj + 1 step = 0 for a in range(Nproj): if self.canceled: return self.progress.message = 'Tilt image No.%d/%d' % (a + 1, Nproj) #print angles[a] ang = tiltAngles[a] * np.pi / 180 projection = tiltSeries[:, :, a] #2D projection image p = np.lib.pad(projection, ((0, 0), (pad_pre, pad_post)), 'constant', constant_values=(0, 0)) #pad zeros p = np.fft.ifftshift(p) p_fftw_object.update_arrays(p, pF) p_fftw_object() probjection_f = pF.copy() if ang < 0: probjection_f = np.conj(pF.copy()) probjection_f[1:, :] = np.flipud(probjection_f[1:, :]) ang = np.pi + ang # Bilinear extrapolation for i in range(0, np.int(np.ceil(Npad / 2)) + 1): ky = i * dk #kz = 0 ky_new = np.cos(ang) * ky #new coord. after rotation kz_new = np.sin(ang) * ky sy = abs(np.floor(ky_new) - ky_new) #calculate weights sz = abs(np.floor(kz_new) - kz_new) for b in range(1, 5): #bilinear extrapolation pz, py, weight = bilinear(kz_new, ky_new, sz, sy, Ny, b) if (py >= 0 and py < Ny and pz >= 0 and pz < Nz / 2 + 1): w[:, py, pz] = w[:, py, pz] + weight v[:, py, pz] = v[:, py, pz] + \ weight * probjection_f[:, i] step += 1 self.progress.value = step self.progress.message = 'Inverse Fourier transform' v[w != 0] = v[w != 0] / w[w != 0] recon_fftw_object.update_arrays(v, recon) recon_fftw_object() recon = np.fft.fftshift(recon) step += 1 self.progress.value = step from vtk import vtkImageData recon_dataset = vtkImageData() recon_dataset.CopyStructure(dataset) utils.set_array(recon_dataset, recon) utils.mark_as_volume(recon_dataset) returnValues = {} returnValues["reconstruction"] = recon_dataset return returnValues
def transform_scalars(self, dataset, Niter=1): """3D Reconstruct from a tilt series using simple TV minimzation""" self.progress.maximum = 1 # Get Tilt angles tiltAngles = utils.get_tilt_angles(dataset) #remove zero tilt anlges if np.count_nonzero(tiltAngles) < tiltAngles.size: tiltAngles = tiltAngles + 0.001 # Get Tilt Series tiltSeries = utils.get_array(dataset) (Nslice, Nray, Nproj) = tiltSeries.shape if tiltSeries is None: raise RuntimeError("No scalars found!") # Generate measurement matrix A = parallelRay(Nray, 1.0, tiltAngles, Nray, 1.0) #A is a sparse matrix recon = np.empty([Nslice, Nray, Nray], dtype=float, order='F') A = A.todense() (Nslice, Nray, Nproj) = tiltSeries.shape (Nrow, Ncol) = A.shape rowInnerProduct = np.zeros(Nrow) row = np.zeros(Ncol) f = np.zeros(Ncol) # Placeholder for 2d image alpha = 0.2 ng = 30 beta_red = 0.995 beta = 1.0 # Calculate row inner product, preparation for ART recon for j in range(Nrow): row[:] = A[j, ].copy() rowInnerProduct[j] = np.dot(row, row) self.progress.maximum = Niter step = 0 t0 = time.time() counter = 1 etcMessage = 'Estimated time to complete: n/a' for i in range(Niter): #main loop if self.canceled: return self.progress.message = 'Iteration No.%d/%d. ' % ( i + 1, Niter) + etcMessage recon_temp = recon.copy() #ART recon for s in range(Nslice): # f[:] = 0 b = tiltSeries[s, :, :].transpose().flatten() for j in range(Nrow): row[:] = A[j, ].copy() row_f_product = np.dot(row, f) a = (b[j] - row_f_product) / rowInnerProduct[j] f = f + row * a * beta recon[s, :, :] = f.reshape((Nray, Nray)) recon[recon < 0] = 0 #Positivity constraint #calculate tomogram change due to POCS dPOCS = np.linalg.norm(recon_temp - recon) #3D TV minimization for j in range(ng): r = np.lib.pad(recon, ((1, 1), (1, 1), (1, 1)), 'edge') v1n = 3 * r - np.roll(r, 1, axis=0) - \ np.roll(r, 1, axis=1) - np.roll(r, 1, axis=2) # noqa TODO reformat this v1d = np.sqrt( 1e-8 + (r - np.roll(r, 1, axis=0))**2 + (r - np.roll(r, 1, axis=1))**2 + (r - np.roll(r, 1, axis=2))**2) # noqa TODO reformat this v2n = r - np.roll(r, -1, axis=0) v2d = np.sqrt(1e-8 + (np.roll(r, -1, axis=0) - r)**2 + ( np.roll(r, -1, axis=0) - # noqa TODO reformat this np.roll(np.roll(r, -1, axis=0), 1, axis=1))**2 + (np.roll(r, -1, axis=0) - np.roll(np.roll(r, -1, axis=0), 1, axis=2))** 2) # noqa TODO reformat this v3n = r - np.roll(r, -1, axis=1) v3d = np.sqrt(1e-8 + (np.roll(r, -1, axis=1) - np.roll(np.roll(r, -1, axis=1), 1, axis=0))**2 + # noqa TODO reformat this (np.roll(r, -1, axis=1) - r)**2 + # noqa TODO reformat this (np.roll(r, -1, axis=1) - np.roll(np.roll(r, -1, axis=1), 1, axis=2))** 2) # noqa TODO reformat this v4n = r - np.roll(r, -1, axis=2) v4d = np.sqrt( 1e-8 + (np.roll(r, -1, axis=2) - np.roll(np.roll(r, -1, axis=2), 1, axis=0))**2 + # noqa TODO reformat this ( np.roll(r, -1, axis=2) - # noqa TODO reformat this np.roll(np.roll(r, -1, axis=1), 1, axis=1))**2 + (np.roll(r, -1, axis=2) - r)**2) # noqa TODO reformat this v = v1n / v1d + v2n / v2d + v3n / v3d + v4n / v4d v = v[1:-1, 1:-1, 1:-1] v = v / np.linalg.norm(v) recon[:] = recon - alpha * dPOCS * v #adjust parameters beta = beta * beta_red step += 1 self.progress.value = step timeLeft = (time.time() - t0) / counter * \ (Nslice * Niter - counter) counter += 1 timeLeftMin, timeLeftSec = divmod(timeLeft, 60) timeLeftHour, timeLeftMin = divmod(timeLeftMin, 60) etcMessage = 'Estimated time to complete: %02d:%02d:%02d' % ( timeLeftHour, timeLeftMin, timeLeftSec) # Set the result as the new scalars. utils.set_array(dataset, recon) # Mark dataset as volume utils.mark_as_volume(dataset)
def transform_scalars(self, dataset, Niter=1): """3D Reconstruct from a tilt series using simple TV minimzation""" self.progress.maximum = 1 # Get Tilt angles tiltAngles = utils.get_tilt_angles(dataset) #remove zero tilt anlges if np.count_nonzero(tiltAngles) < tiltAngles.size: tiltAngles = tiltAngles + 0.001 # Get Tilt Series tiltSeries = utils.get_array(dataset) (Nslice, Nray, Nproj) = tiltSeries.shape if tiltSeries is None: raise RuntimeError("No scalars found!") # Generate measurement matrix A = parallelRay(Nray, 1.0, tiltAngles, Nray, 1.0) #A is a sparse matrix recon = np.empty([Nslice, Nray, Nray], dtype=float, order='F') A = A.todense() (Nslice, Nray, Nproj) = tiltSeries.shape (Nrow, Ncol) = A.shape rowInnerProduct = np.zeros(Nrow) row = np.zeros(Ncol) f = np.zeros(Ncol) # Placeholder for 2d image alpha = 0.2 ng = 30 beta_red = 0.995 beta = 1.0 # Calculate row inner product, preparation for ART recon for j in range(Nrow): row[:] = A[j, ].copy() rowInnerProduct[j] = np.dot(row, row) self.progress.maximum = Niter step = 0 t0 = time.time() counter = 1 etcMessage = 'Estimated time to complete: n/a' for i in range(Niter): #main loop if self.canceled: return self.progress.message = 'Iteration No.%d/%d. ' % ( i + 1, Niter) + etcMessage recon_temp = recon.copy() #ART recon for s in range(Nslice): # f[:] = 0 b = tiltSeries[s, :, :].transpose().flatten() for j in range(Nrow): row[:] = A[j, ].copy() row_f_product = np.dot(row, f) a = (b[j] - row_f_product) / rowInnerProduct[j] f = f + row * a * beta recon[s, :, :] = f.reshape((Nray, Nray)) recon[recon < 0] = 0 #Positivity constraint #calculate tomogram change due to POCS dPOCS = np.linalg.norm(recon_temp - recon) #3D TV minimization for j in range(ng): r = np.lib.pad(recon, ((1, 1), (1, 1), (1, 1)), 'edge') v1n = 3 * r - np.roll(r, 1, axis=0) - \ np.roll(r, 1, axis=1) - np.roll(r, 1, axis=2) # noqa TODO reformat this v1d = np.sqrt(1e-8 + (r - np.roll(r, 1, axis=0))**2 + (r - np.roll(r, 1, axis=1))**2 + (r - np.roll(r, 1, axis=2))**2) # noqa TODO reformat this v2n = r - np.roll(r, -1, axis=0) v2d = np.sqrt(1e-8 + (np.roll(r, -1, axis=0) - r)**2 + (np.roll(r, -1, axis=0) - # noqa TODO reformat this np.roll(np.roll(r, -1, axis=0), 1, axis=1))**2 + (np.roll(r, -1, axis=0) - np.roll(np.roll(r, -1, axis=0), 1, axis=2))**2) # noqa TODO reformat this v3n = r - np.roll(r, -1, axis=1) v3d = np.sqrt(1e-8 + (np.roll(r, -1, axis=1) - np.roll(np.roll(r, -1, axis=1), 1, axis=0))**2 + # noqa TODO reformat this (np.roll(r, -1, axis=1) - r)**2 + # noqa TODO reformat this (np.roll(r, -1, axis=1) - np.roll(np.roll(r, -1, axis=1), 1, axis=2))**2) # noqa TODO reformat this v4n = r - np.roll(r, -1, axis=2) v4d = np.sqrt(1e-8 + (np.roll(r, -1, axis=2) - np.roll(np.roll(r, -1, axis=2), 1, axis=0))**2 + # noqa TODO reformat this (np.roll(r, -1, axis=2) - # noqa TODO reformat this np.roll(np.roll(r, -1, axis=1), 1, axis=1))**2 + (np.roll(r, -1, axis=2) - r)**2) # noqa TODO reformat this v = v1n / v1d + v2n / v2d + v3n / v3d + v4n / v4d v = v[1:-1, 1:-1, 1:-1] v = v / np.linalg.norm(v) recon[:] = recon - alpha * dPOCS * v #adjust parameters beta = beta * beta_red step += 1 self.progress.value = step timeLeft = (time.time() - t0) / counter * \ (Nslice * Niter - counter) counter += 1 timeLeftMin, timeLeftSec = divmod(timeLeft, 60) timeLeftHour, timeLeftMin = divmod(timeLeftMin, 60) etcMessage = 'Estimated time to complete: %02d:%02d:%02d' % ( timeLeftHour, timeLeftMin, timeLeftSec) # Set the result as the new scalars. utils.set_array(dataset, recon) # Mark dataset as volume utils.mark_as_volume(dataset)