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, 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, 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=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 create_child_dataset(self): new_data = utils.make_child_dataset(self._data_object) return Dataset(new_data, self._data_source)
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=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, 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, 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