Mercurial > repos > rv43 > tomo
comparison tomo.py @ 41:ef5c2f7b49ec draft
"planemo upload for repository https://github.com/rolfverberg/galaxytools commit 0d207c80e38a6019595ebe178f5678372b75f3e7"
| author | rv43 |
|---|---|
| date | Thu, 21 Apr 2022 14:21:38 +0000 |
| parents | fa94fe25ca46 |
| children | 0b9ce9489ecc |
comparison
equal
deleted
inserted
replaced
| 40:fa94fe25ca46 | 41:ef5c2f7b49ec |
|---|---|
| 18 import pyinputplus as pyip | 18 import pyinputplus as pyip |
| 19 except: | 19 except: |
| 20 pass | 20 pass |
| 21 import argparse | 21 import argparse |
| 22 import numpy as np | 22 import numpy as np |
| 23 import numexpr as ne | 23 try: |
| 24 import numexpr as ne | |
| 25 except: | |
| 26 pass | |
| 24 import multiprocessing as mp | 27 import multiprocessing as mp |
| 25 import scipy.ndimage as spi | 28 try: |
| 26 import tomopy | 29 import scipy.ndimage as spi |
| 30 except: | |
| 31 pass | |
| 32 try: | |
| 33 import tomopy | |
| 34 except: | |
| 35 pass | |
| 27 from time import time | 36 from time import time |
| 28 from skimage.transform import iradon | 37 try: |
| 29 from skimage.restoration import denoise_tv_chambolle | 38 from skimage.transform import iradon |
| 39 except: | |
| 40 pass | |
| 41 try: | |
| 42 from skimage.restoration import denoise_tv_chambolle | |
| 43 except: | |
| 44 pass | |
| 30 | 45 |
| 31 import msnc_tools as msnc | 46 import msnc_tools as msnc |
| 47 | |
| 48 # the following tomopy routines don't run with more than 24 cores on Galaxy-Dev | |
| 49 # - tomopy.find_center_vo | |
| 50 # - tomopy.prep.stripe.remove_stripe_fw | |
| 51 num_core_tomopy_limit = 24 | |
| 32 | 52 |
| 33 class set_numexpr_threads: | 53 class set_numexpr_threads: |
| 34 | 54 |
| 35 def __init__(self, num_core): | 55 def __init__(self, num_core): |
| 36 cpu_count = mp.cpu_count() | 56 cpu_count = mp.cpu_count() |
| 628 if self.is_valid: | 648 if self.is_valid: |
| 629 self.cf.saveFile(self.config_out) | 649 self.cf.saveFile(self.config_out) |
| 630 | 650 |
| 631 return | 651 return |
| 632 | 652 |
| 633 def _genDark(self, tdf_files, dark_field_pngname): | 653 def _genDark(self, tdf_files): |
| 634 """Generate dark field. | 654 """Generate dark field. |
| 635 """ | 655 """ |
| 636 # Load the dark field images | 656 # Load the dark field images |
| 637 logging.debug('Loading dark field...') | 657 logging.debug('Loading dark field...') |
| 638 dark_field = self.config['dark_field'] | 658 dark_field = self.config['dark_field'] |
| 649 tdf_mean = np.nanmean(self.tdf) | 669 tdf_mean = np.nanmean(self.tdf) |
| 650 logging.debug(f'tdf_cutoff = {tdf_cutoff}') | 670 logging.debug(f'tdf_cutoff = {tdf_cutoff}') |
| 651 logging.debug(f'tdf_mean = {tdf_mean}') | 671 logging.debug(f'tdf_mean = {tdf_mean}') |
| 652 np.nan_to_num(self.tdf, copy=False, nan=tdf_mean, posinf=tdf_mean, neginf=0.) | 672 np.nan_to_num(self.tdf, copy=False, nan=tdf_mean, posinf=tdf_mean, neginf=0.) |
| 653 if self.galaxy_flag: | 673 if self.galaxy_flag: |
| 654 msnc.quickImshow(self.tdf, title='dark field', name=dark_field_pngname, | 674 msnc.quickImshow(self.tdf, title='dark field', path='setup_pngs', |
| 655 save_fig=True, save_only=True) | 675 save_fig=True, save_only=True) |
| 656 elif not self.test_mode: | 676 elif not self.test_mode: |
| 657 msnc.quickImshow(self.tdf, title='dark field', path=self.output_folder, | 677 msnc.quickImshow(self.tdf, title='dark field', path=self.output_folder, |
| 658 save_fig=self.save_plots, save_only=self.save_plots_only) | 678 save_fig=self.save_plots, save_only=self.save_plots_only) |
| 659 | 679 |
| 660 def _genBright(self, tbf_files, bright_field_pngname): | 680 def _genBright(self, tbf_files): |
| 661 """Generate bright field. | 681 """Generate bright field. |
| 662 """ | 682 """ |
| 663 # Load the bright field images | 683 # Load the bright field images |
| 664 logging.debug('Loading bright field...') | 684 logging.debug('Loading bright field...') |
| 665 bright_field = self.config['bright_field'] | 685 bright_field = self.config['bright_field'] |
| 683 if self.tdf.size: | 703 if self.tdf.size: |
| 684 self.tbf -= self.tdf | 704 self.tbf -= self.tdf |
| 685 else: | 705 else: |
| 686 logging.warning('Dark field unavailable') | 706 logging.warning('Dark field unavailable') |
| 687 if self.galaxy_flag: | 707 if self.galaxy_flag: |
| 688 msnc.quickImshow(self.tbf, title='bright field', name=bright_field_pngname, | 708 msnc.quickImshow(self.tbf, title='bright field', path='setup_pngs', |
| 689 save_fig=True, save_only=True) | 709 save_fig=True, save_only=True) |
| 690 elif not self.test_mode: | 710 elif not self.test_mode: |
| 691 msnc.quickImshow(self.tbf, title='bright field', path=self.output_folder, | 711 msnc.quickImshow(self.tbf, title='bright field', path=self.output_folder, |
| 692 save_fig=self.save_plots, save_only=self.save_plots_only) | 712 save_fig=self.save_plots, save_only=self.save_plots_only) |
| 693 | 713 |
| 694 def _setDetectorBounds(self, tomo_stack_files, tomo_field_pngname, detectorbounds_pngname): | 714 def _setDetectorBounds(self, tomo_stack_files): |
| 695 """Set vertical detector bounds for image stack. | 715 """Set vertical detector bounds for image stack. |
| 696 """ | 716 """ |
| 697 preprocess = self.config.get('preprocess') | 717 preprocess = self.config.get('preprocess') |
| 698 if preprocess is None: | 718 if preprocess is None: |
| 699 img_x_bounds = [None, None] | 719 img_x_bounds = [None, None] |
| 727 if num_tomo_stacks > 1: | 747 if num_tomo_stacks > 1: |
| 728 delta_z = stacks[1]['ref_height']-stacks[0]['ref_height'] | 748 delta_z = stacks[1]['ref_height']-stacks[0]['ref_height'] |
| 729 for i in range(2, num_tomo_stacks): | 749 for i in range(2, num_tomo_stacks): |
| 730 delta_z = min(delta_z, stacks[i]['ref_height']-stacks[i-1]['ref_height']) | 750 delta_z = min(delta_z, stacks[i]['ref_height']-stacks[i-1]['ref_height']) |
| 731 logging.debug(f'delta_z = {delta_z}') | 751 logging.debug(f'delta_z = {delta_z}') |
| 732 num_x_min = int(delta_z/pixel_size)+1 | 752 num_x_min = int((delta_z-0.5*pixel_size)/pixel_size) |
| 733 logging.debug(f'num_x_min = {num_x_min}') | 753 logging.debug(f'num_x_min = {num_x_min}') |
| 734 if num_x_min > self.tbf.shape[0]: | 754 if num_x_min > self.tbf.shape[0]: |
| 735 logging.warning('Image bounds and pixel size prevent seamless stacking') | 755 logging.warning('Image bounds and pixel size prevent seamless stacking') |
| 736 num_x_min = self.tbf.shape[0] | 756 num_x_min = None |
| 737 | 757 |
| 738 # Select image bounds | 758 # Select image bounds |
| 739 if self.galaxy_flag: | 759 if self.galaxy_flag: |
| 740 if num_x_min is None or num_x_min >= self.tbf.shape[0]: | 760 x_sum = np.sum(self.tbf, 1) |
| 741 img_x_bounds = [0, self.tbf.shape[0]] | |
| 742 else: | |
| 743 margin = int(num_x_min/10) | |
| 744 offset = min(0, int((self.tbf.shape[0]-num_x_min)/2-margin)) | |
| 745 img_x_bounds = [offset, num_x_min+offset+2*margin] | |
| 746 tomo_stack = msnc.loadImageStack(tomo_stack_files[0], self.config['data_filetype'], | |
| 747 stacks[0]['img_offset'], 1) | |
| 748 x_sum = np.sum(tomo_stack[0,:,:], 1) | |
| 749 x_sum_min = x_sum.min() | 761 x_sum_min = x_sum.min() |
| 750 x_sum_max = x_sum.max() | 762 x_sum_max = x_sum.max() |
| 751 title = f'tomography image at theta={self.config["theta_range"]["start"]}' | 763 x_low = 0 |
| 752 msnc.quickImshow(tomo_stack[0,:,:], title=title, name=tomo_field_pngname, | 764 x_upp = x_sum.size |
| 753 save_fig=True, save_only=True, show_grid=True) | 765 if num_x_min is not None: |
| 766 fit = msnc.fitStep(y=x_sum, model='rectangle', form='atan') | |
| 767 x_low = fit.get('center1', None) | |
| 768 x_upp = fit.get('center2', None) | |
| 769 sig_low = fit.get('sigma1', None) | |
| 770 sig_upp = fit.get('sigma2', None) | |
| 771 if (x_low is not None and x_upp is not None and sig_low is not None and | |
| 772 sig_upp is not None and 0 <= x_low < x_upp <= x_sum.size and | |
| 773 (sig_low+sig_upp)/(x_upp-x_low) < 0.1): | |
| 774 if num_tomo_stacks == 1 or num_x_min is None: | |
| 775 x_low = int(x_low-(x_upp-x_low)/10) | |
| 776 x_upp = int(x_upp+(x_upp-x_low)/10) | |
| 777 else: | |
| 778 x_low = int((x_low+x_upp)/2-num_x_min/2) | |
| 779 x_upp = x_low+num_x_min | |
| 780 if x_low < 0: | |
| 781 x_low = 0 | |
| 782 if x_upp > x_sum.size: | |
| 783 x_upp = x_sum.size | |
| 784 else: | |
| 785 x_low = 0 | |
| 786 x_upp = x_sum.size | |
| 754 msnc.quickPlot((range(x_sum.size), x_sum), | 787 msnc.quickPlot((range(x_sum.size), x_sum), |
| 755 ([img_x_bounds[0], img_x_bounds[0]], [x_sum_min, x_sum_max], 'r-'), | 788 ([x_low, x_low], [x_sum_min, x_sum_max], 'r-'), |
| 756 ([img_x_bounds[1]-1, img_x_bounds[1]-1], [x_sum_min, x_sum_max], 'r-'), | 789 ([x_upp-1, x_upp-1], [x_sum_min, x_sum_max], 'r-'), |
| 757 title='sum over theta and y', name=detectorbounds_pngname, | 790 title=f'sum bright field over theta/y (row bounds: [{x_low}, {x_upp}])', |
| 758 save_fig=True, save_only=True, show_grid=True) | 791 path='setup_pngs', name='detectorbounds.png', save_fig=True, save_only=True, |
| 792 show_grid=True) | |
| 793 for i,stack in enumerate(stacks): | |
| 794 tomo_stack = msnc.loadImageStack(tomo_stack_files[i], self.config['data_filetype'], | |
| 795 stack['img_offset'], 1) | |
| 796 tomo_stack = tomo_stack[0,:,:] | |
| 797 if num_x_min is not None: | |
| 798 tomo_stack_max = tomo_stack.max() | |
| 799 tomo_stack[x_low,:] = tomo_stack_max | |
| 800 tomo_stack[x_upp-1,:] = tomo_stack_max | |
| 801 title = f'tomography image at theta={self.config["theta_range"]["start"]}' | |
| 802 msnc.quickImshow(tomo_stack, title=title, path='setup_pngs', | |
| 803 name=f'tomo_{stack["index"]}.png', save_fig=True, save_only=True, | |
| 804 show_grid=True) | |
| 805 del tomo_stack | |
| 759 | 806 |
| 760 # Update config and save to file | 807 # Update config and save to file |
| 808 img_x_bounds = [x_low, x_upp] | |
| 809 logging.debug(f'img_x_bounds: {img_x_bounds}') | |
| 761 if preprocess is None: | 810 if preprocess is None: |
| 762 self.cf.config['preprocess'] = {'img_x_bounds' : img_x_bounds} | 811 self.cf.config['preprocess'] = {'img_x_bounds' : img_x_bounds} |
| 763 else: | 812 else: |
| 764 preprocess['img_x_bounds'] = img_x_bounds | 813 preprocess['img_x_bounds'] = img_x_bounds |
| 765 self.cf.saveFile(self.config_out) | 814 self.cf.saveFile(self.config_out) |
| 830 title='sum over theta and y') | 879 title='sum over theta and y') |
| 831 print(f'lower bound = {img_x_bounds[0]} (inclusive)\n'+ | 880 print(f'lower bound = {img_x_bounds[0]} (inclusive)\n'+ |
| 832 f'upper bound = {img_x_bounds[1]} (exclusive)]') | 881 f'upper bound = {img_x_bounds[1]} (exclusive)]') |
| 833 use_bounds = pyip.inputYesNo('Accept these bounds ([y]/n)?: ', blank=True) | 882 use_bounds = pyip.inputYesNo('Accept these bounds ([y]/n)?: ', blank=True) |
| 834 if use_bounds == 'no': | 883 if use_bounds == 'no': |
| 884 use_fit = 'no' | |
| 835 fit = msnc.fitStep(y=x_sum, model='rectangle', form='atan') | 885 fit = msnc.fitStep(y=x_sum, model='rectangle', form='atan') |
| 836 x_low = fit.get('center1', None) | 886 x_low = fit.get('center1', None) |
| 837 x_upp = fit.get('center2', None) | 887 x_upp = fit.get('center2', None) |
| 838 if (x_low is not None and x_low >= 0 and x_upp is not None and | 888 sig_low = fit.get('sigma1', None) |
| 839 x_low < x_upp < x_sum.size): | 889 sig_upp = fit.get('sigma2', None) |
| 840 x_low = int(x_low-(x_upp-x_low)/10) | 890 if (x_low is not None and x_upp is not None and sig_low is not None and |
| 891 sig_upp is not None and 0 <= x_low < x_upp <= x_sum.size and | |
| 892 (sig_low+sig_upp)/(x_upp-x_low) < 0.1): | |
| 893 if num_tomo_stacks == 1 or num_x_min is None: | |
| 894 x_low = int(x_low-(x_upp-x_low)/10) | |
| 895 x_upp = int(x_upp+(x_upp-x_low)/10) | |
| 896 else: | |
| 897 x_low = int((x_low+x_upp)/2-num_x_min/2) | |
| 898 x_upp = x_low+num_x_min | |
| 841 if x_low < 0: | 899 if x_low < 0: |
| 842 x_low = 0 | 900 x_low = 0 |
| 843 x_upp = int(x_upp+(x_upp-x_low)/10) | 901 if x_upp > x_sum.size: |
| 844 if x_upp >= x_sum.size: | |
| 845 x_upp = x_sum.size | 902 x_upp = x_sum.size |
| 846 tmp = np.copy(self.tbf) | 903 tmp = np.copy(self.tbf) |
| 847 tmp_max = tmp.max() | 904 tmp_max = tmp.max() |
| 848 tmp[x_low,:] = tmp_max | 905 tmp[x_low,:] = tmp_max |
| 849 tmp[x_upp-1,:] = tmp_max | 906 tmp[x_upp-1,:] = tmp_max |
| 852 del tmp | 909 del tmp |
| 853 msnc.quickPlot((range(x_sum.size), x_sum), | 910 msnc.quickPlot((range(x_sum.size), x_sum), |
| 854 ([x_low, x_low], [x_sum_min, x_sum_max], 'r-'), | 911 ([x_low, x_low], [x_sum_min, x_sum_max], 'r-'), |
| 855 ([x_upp, x_upp], [x_sum_min, x_sum_max], 'r-'), | 912 ([x_upp, x_upp], [x_sum_min, x_sum_max], 'r-'), |
| 856 title='sum over theta and y') | 913 title='sum over theta and y') |
| 857 print(f'lower bound = {x_low} (inclusive)\nupper bound = {x_upp} (exclusive)]') | 914 print(f'lower bound = {x_low} (inclusive)') |
| 915 print(f'upper bound = {x_upp} (exclusive)]') | |
| 858 use_fit = pyip.inputYesNo('Accept these bounds ([y]/n)?: ', blank=True) | 916 use_fit = pyip.inputYesNo('Accept these bounds ([y]/n)?: ', blank=True) |
| 859 if use_fit == 'no': | 917 if use_fit == 'no': |
| 860 img_x_bounds = msnc.selectArrayBounds(x_sum, img_x_bounds[0], img_x_bounds[1], | 918 img_x_bounds = msnc.selectArrayBounds(x_sum, img_x_bounds[0], img_x_bounds[1], |
| 861 num_x_min, 'sum over theta and y') | 919 num_x_min, 'sum over theta and y') |
| 862 else: | 920 else: |
| 863 img_x_bounds = [x_low, x_upp] | 921 img_x_bounds = [x_low, x_upp] |
| 864 if num_x_min is not None and img_x_bounds[1]-img_x_bounds[0]+1 < num_x_min: | 922 if num_x_min is not None and img_x_bounds[1]-img_x_bounds[0]+1 < num_x_min: |
| 865 logging.warning('Image bounds and pixel size prevent seamless stacking') | 923 logging.warning('Image bounds and pixel size prevent seamless stacking') |
| 866 msnc.quickPlot(range(img_x_bounds[0], img_x_bounds[1]), | 924 #msnc.quickPlot(range(img_x_bounds[0], img_x_bounds[1]), |
| 867 x_sum[img_x_bounds[0]:img_x_bounds[1]], | 925 # x_sum[img_x_bounds[0]:img_x_bounds[1]], |
| 926 # title='sum over theta and y', path=self.output_folder, | |
| 927 # save_fig=self.save_plots, save_only=True) | |
| 928 msnc.quickPlot((range(x_sum.size), x_sum), | |
| 929 ([img_x_bounds[0], img_x_bounds[0]], [x_sum_min, x_sum_max], 'r-'), | |
| 930 ([img_x_bounds[1], img_x_bounds[1]], [x_sum_min, x_sum_max], 'r-'), | |
| 868 title='sum over theta and y', path=self.output_folder, | 931 title='sum over theta and y', path=self.output_folder, |
| 869 save_fig=self.save_plots, save_only=True) | 932 save_fig=self.save_plots, save_only=True) |
| 870 del x_sum | 933 del x_sum |
| 934 for i,stack in enumerate(stacks): | |
| 935 tomo_stack = msnc.loadImageStack(tomo_stack_files[i], self.config['data_filetype'], | |
| 936 stack['img_offset'], 1) | |
| 937 tomo_stack = tomo_stack[0,:,:] | |
| 938 if num_x_min is not None: | |
| 939 tomo_stack_max = tomo_stack.max() | |
| 940 tomo_stack[img_x_bounds[0],:] = tomo_stack_max | |
| 941 tomo_stack[img_x_bounds[1]-1,:] = tomo_stack_max | |
| 942 title = f'tomography image at theta={self.config["theta_range"]["start"]}' | |
| 943 msnc.quickImshow(tomo_stack, title=title, path='setup_pngs', | |
| 944 name=f'tomo_{stack["index"]}.png', save_fig=self.save_plots, save_only=True, | |
| 945 show_grid=True) | |
| 946 del tomo_stack | |
| 871 logging.debug(f'img_x_bounds: {img_x_bounds}') | 947 logging.debug(f'img_x_bounds: {img_x_bounds}') |
| 872 | 948 |
| 873 if self.save_plots_only: | 949 if self.save_plots_only: |
| 874 msnc.clearFig('bright field') | 950 msnc.clearFig('bright field') |
| 875 msnc.clearFig('sum over theta and y') | 951 msnc.clearFig('sum over theta and y') |
| 1146 # recon_sinogram = filters.gaussian(recon_sinogram, 3.0) | 1222 # recon_sinogram = filters.gaussian(recon_sinogram, 3.0) |
| 1147 recon_sinogram = spi.gaussian_filter(recon_sinogram, 0.5) | 1223 recon_sinogram = spi.gaussian_filter(recon_sinogram, 0.5) |
| 1148 recon_clean = np.expand_dims(recon_sinogram, axis=0) | 1224 recon_clean = np.expand_dims(recon_sinogram, axis=0) |
| 1149 del recon_sinogram | 1225 del recon_sinogram |
| 1150 t1 = time() | 1226 t1 = time() |
| 1151 logging.info(f'running tomopy.misc.corr.remove_ring on {num_core} cores ...') | 1227 logging.debug(f'running remove_ring on {num_core} cores ...') |
| 1152 recon_clean = tomopy.misc.corr.remove_ring(recon_clean, rwidth=17, ncore=num_core) | 1228 recon_clean = tomopy.misc.corr.remove_ring(recon_clean, rwidth=17, ncore=num_core) |
| 1153 logging.info(f'... tomopy.misc.corr.remove_ring took {time()-t1:.2f} seconds!') | 1229 logging.debug(f'... remove_ring took {time()-t1:.2f} seconds!') |
| 1154 logging.debug(f'filtering and removing ring artifact took {time()-t0:.2f} seconds!') | 1230 logging.debug(f'filtering and removing ring artifact took {time()-t0:.2f} seconds!') |
| 1155 return recon_clean | 1231 return recon_clean |
| 1156 | 1232 |
| 1157 def _plotEdgesOnePlane(self, recon_plane, title, path=None, weight=0.001): | 1233 def _plotEdgesOnePlane(self, recon_plane, title, path=None, weight=0.001): |
| 1158 # RV parameters for the denoise, gaussian, and ring removal will be different for different feature sizes | 1234 # RV parameters for the denoise, gaussian, and ring removal will be different for different feature sizes |
| 1175 def _findCenterOnePlane(self, sinogram, row, thetas_deg, eff_pixel_size, cross_sectional_dim, | 1251 def _findCenterOnePlane(self, sinogram, row, thetas_deg, eff_pixel_size, cross_sectional_dim, |
| 1176 tol=0.1, num_core=1, galaxy_param=None): | 1252 tol=0.1, num_core=1, galaxy_param=None): |
| 1177 """Find center for a single tomography plane. | 1253 """Find center for a single tomography plane. |
| 1178 """ | 1254 """ |
| 1179 if self.galaxy_flag: | 1255 if self.galaxy_flag: |
| 1180 assert(galaxy_param) | 1256 assert(isinstance(galaxy_param, dict)) |
| 1181 if not os.path.exists('find_center_pngs'): | 1257 if not os.path.exists('find_center_pngs'): |
| 1182 os.mkdir('find_center_pngs') | 1258 os.mkdir('find_center_pngs') |
| 1183 # sinogram index order: theta,column | 1259 # sinogram index order: theta,column |
| 1184 # need index order column,theta for iradon, so take transpose | 1260 # need index order column,theta for iradon, so take transpose |
| 1185 sinogram_T = sinogram.T | 1261 sinogram_T = sinogram.T |
| 1186 center = sinogram.shape[1]/2 | 1262 center = sinogram.shape[1]/2 |
| 1187 | 1263 |
| 1188 # try automatic center finding routines for initial value | 1264 # try automatic center finding routines for initial value |
| 1189 t0 = time() | 1265 t0 = time() |
| 1190 if num_core > 24: | 1266 if num_core > num_core_tomopy_limit: |
| 1191 logging.info('running tomopy.find_center_vo on 24 cores ...') | 1267 logging.debug(f'running find_center_vo on {num_core_tomopy_limit} cores ...') |
| 1192 tomo_center = tomopy.find_center_vo(sinogram, ncore=24) | 1268 tomo_center = tomopy.find_center_vo(sinogram, ncore=num_core_tomopy_limit) |
| 1193 else: | 1269 else: |
| 1194 logging.info(f'running tomopy.find_center_vo on {num_core} cores ...') | 1270 logging.debug(f'running find_center_vo on {num_core} cores ...') |
| 1195 tomo_center = tomopy.find_center_vo(sinogram, ncore=num_core) | 1271 tomo_center = tomopy.find_center_vo(sinogram, ncore=num_core) |
| 1196 logging.info(f'... tomopy.find_center_vo took {time()-t0:.2f} seconds!') | 1272 logging.debug(f'... find_center_vo took {time()-t0:.2f} seconds!') |
| 1197 center_offset_vo = tomo_center-center | 1273 center_offset_vo = tomo_center-center |
| 1198 if self.test_mode: | 1274 if self.test_mode: |
| 1199 logging.info(f'Center at row {row} using Nghia Vo’s method = {center_offset_vo:.2f}') | 1275 logging.info(f'Center at row {row} using Nghia Vo’s method = {center_offset_vo:.2f}') |
| 1200 del sinogram_T | 1276 del sinogram_T |
| 1201 return float(center_offset_vo) | 1277 return float(center_offset_vo) |
| 1202 elif self.galaxy_flag: | 1278 elif self.galaxy_flag: |
| 1203 logging.info(f'Center at row {row} using Nghia Vo’s method = {center_offset_vo:.2f}') | 1279 logging.info(f'Center at row {row} using Nghia Vo’s method = {center_offset_vo:.2f}') |
| 1204 t0 = time() | 1280 t0 = time() |
| 1205 logging.info(f'running self._reconstructOnePlane on {num_core} cores ...') | 1281 logging.debug(f'running _reconstructOnePlane on {num_core} cores ...') |
| 1206 recon_plane = self._reconstructOnePlane(sinogram_T, tomo_center, thetas_deg, | 1282 recon_plane = self._reconstructOnePlane(sinogram_T, tomo_center, thetas_deg, |
| 1207 eff_pixel_size, cross_sectional_dim, False, num_core) | 1283 eff_pixel_size, cross_sectional_dim, False, num_core) |
| 1208 logging.info(f'... self._reconstructOnePlane took {time()-t0:.2f} seconds!') | 1284 logging.debug(f'... _reconstructOnePlane took {time()-t0:.2f} seconds!') |
| 1209 title = f'edges row{row} center offset{center_offset_vo:.2f} Vo' | 1285 title = f'edges row{row} center offset{center_offset_vo:.2f} Vo' |
| 1210 self._plotEdgesOnePlane(recon_plane, title, path='find_center_pngs') | 1286 self._plotEdgesOnePlane(recon_plane, title, path='find_center_pngs') |
| 1211 del recon_plane | 1287 del recon_plane |
| 1212 if not galaxy_param['center_type_selector']: | 1288 if not galaxy_param['center_type_selector']: |
| 1213 del sinogram_T | 1289 del sinogram_T |
| 1277 num_center_offset = 1+int((center_offset_upp-center_offset_low)/center_offset_step) | 1353 num_center_offset = 1+int((center_offset_upp-center_offset_low)/center_offset_step) |
| 1278 center_offsets = np.linspace(center_offset_low, center_offset_upp, num_center_offset) | 1354 center_offsets = np.linspace(center_offset_low, center_offset_upp, num_center_offset) |
| 1279 for center_offset in center_offsets: | 1355 for center_offset in center_offsets: |
| 1280 if center_offset == center_offset_vo: | 1356 if center_offset == center_offset_vo: |
| 1281 continue | 1357 continue |
| 1282 logging.info(f'center_offset = {center_offset:.2f}') | |
| 1283 t0 = time() | 1358 t0 = time() |
| 1284 logging.info(f'running self._reconstructOnePlane on {num_core} cores ...') | 1359 logging.debug(f'running _reconstructOnePlane on {num_core} cores ...') |
| 1285 recon_plane = self._reconstructOnePlane(sinogram_T, center_offset+center, | 1360 recon_plane = self._reconstructOnePlane(sinogram_T, center_offset+center, |
| 1286 thetas_deg, eff_pixel_size, cross_sectional_dim, False, num_core) | 1361 thetas_deg, eff_pixel_size, cross_sectional_dim, False, num_core) |
| 1287 logging.info(f'... self._reconstructOnePlane took {time()-t0:.2f} seconds!') | 1362 logging.debug(f'... _reconstructOnePlane took {time()-t0:.2f} seconds!') |
| 1288 title = f'edges row{row} center_offset{center_offset:.2f}' | 1363 title = f'edges row{row} center_offset{center_offset:.2f}' |
| 1289 if self.galaxy_flag: | 1364 if self.galaxy_flag: |
| 1290 self._plotEdgesOnePlane(recon_plane, title, path='find_center_pngs') | 1365 self._plotEdgesOnePlane(recon_plane, title, path='find_center_pngs') |
| 1291 else: | 1366 else: |
| 1292 self._plotEdgesOnePlane(recon_plane, title) | 1367 self._plotEdgesOnePlane(recon_plane, title) |
| 1333 raise ValueError('center_offsets dimension mismatch in reconstructOneTomoStack') | 1408 raise ValueError('center_offsets dimension mismatch in reconstructOneTomoStack') |
| 1334 centers = center_offsets | 1409 centers = center_offsets |
| 1335 centers += tomo_stack.shape[2]/2 | 1410 centers += tomo_stack.shape[2]/2 |
| 1336 if True: | 1411 if True: |
| 1337 t0 = time() | 1412 t0 = time() |
| 1338 if num_core > 24: | 1413 if num_core > num_core_tomopy_limit: |
| 1339 logging.info(f'running tomopy.prep.stripe.remove_stripe_fw on 24 cores ...') | 1414 logging.debug('running remove_stripe_fw on {num_core_tomopy_limit} cores ...') |
| 1340 tomo_stack = tomopy.prep.stripe.remove_stripe_fw( | 1415 tomo_stack = tomopy.prep.stripe.remove_stripe_fw( |
| 1341 tomo_stack[row_bounds[0]:row_bounds[1]], sigma=sigma, ncore=24) | 1416 tomo_stack[row_bounds[0]:row_bounds[1]], sigma=sigma, |
| 1417 ncore=num_core_tomopy_limit) | |
| 1342 else: | 1418 else: |
| 1343 logging.info(f'running tomopy.prep.stripe.remove_stripe_fw on {num_core} cores ...') | 1419 logging.debug(f'running remove_stripe_fw on {num_core} cores ...') |
| 1344 tomo_stack = tomopy.prep.stripe.remove_stripe_fw( | 1420 tomo_stack = tomopy.prep.stripe.remove_stripe_fw( |
| 1345 tomo_stack[row_bounds[0]:row_bounds[1]], sigma=sigma, ncore=num_core) | 1421 tomo_stack[row_bounds[0]:row_bounds[1]], sigma=sigma, ncore=num_core) |
| 1346 logging.info(f'... tomopy.prep.stripe.remove_stripe_fw took {time()-t0:.2f} seconds!') | 1422 logging.debug(f'... tomopy.prep.stripe.remove_stripe_fw took {time()-t0:.2f} seconds!') |
| 1347 else: | 1423 else: |
| 1348 tomo_stack = tomo_stack[row_bounds[0]:row_bounds[1]] | 1424 tomo_stack = tomo_stack[row_bounds[0]:row_bounds[1]] |
| 1349 logging.info('performing initial reconstruction') | 1425 logging.debug('performing initial reconstruction') |
| 1350 t0 = time() | 1426 t0 = time() |
| 1351 logging.info(f'running tomopy.recon on {num_core} cores ...') | 1427 logging.debug(f'running recon on {num_core} cores ...') |
| 1352 tomo_recon_stack = tomopy.recon(tomo_stack, thetas, centers, sinogram_order=True, | 1428 tomo_recon_stack = tomopy.recon(tomo_stack, thetas, centers, sinogram_order=True, |
| 1353 algorithm=algorithm, ncore=num_core) | 1429 algorithm=algorithm, ncore=num_core) |
| 1354 logging.info(f'... tomopy.recon took {time()-t0:.2f} seconds!') | 1430 logging.debug(f'... recon took {time()-t0:.2f} seconds!') |
| 1355 if run_secondary_sirt and secondary_iter > 0: | 1431 if run_secondary_sirt and secondary_iter > 0: |
| 1356 logging.info(f'running {secondary_iter} secondary iterations') | 1432 logging.debug(f'running {secondary_iter} secondary iterations') |
| 1357 #options = {'method':'SIRT_CUDA', 'proj_type':'cuda', 'num_iter':secondary_iter} | 1433 #options = {'method':'SIRT_CUDA', 'proj_type':'cuda', 'num_iter':secondary_iter} |
| 1358 #RV: doesn't work for me: "Error: CUDA error 803: system has unsupported display driver / | 1434 #RV: doesn't work for me: "Error: CUDA error 803: system has unsupported display driver / |
| 1359 # cuda driver combination." | 1435 # cuda driver combination." |
| 1360 #options = {'method':'SIRT', 'proj_type':'linear', 'MinConstraint': 0, 'num_iter':secondary_iter} | 1436 #options = {'method':'SIRT', 'proj_type':'linear', 'MinConstraint': 0, 'num_iter':secondary_iter} |
| 1361 #SIRT did not finish while running overnight | 1437 #SIRT did not finish while running overnight |
| 1362 #options = {'method':'SART', 'proj_type':'linear', 'num_iter':secondary_iter} | 1438 #options = {'method':'SART', 'proj_type':'linear', 'num_iter':secondary_iter} |
| 1363 options = {'method':'SART', 'proj_type':'linear', 'MinConstraint': 0, | 1439 options = {'method':'SART', 'proj_type':'linear', 'MinConstraint': 0, |
| 1364 'num_iter':secondary_iter} | 1440 'num_iter':secondary_iter} |
| 1365 t0 = time() | 1441 t0 = time() |
| 1366 logging.info(f'running tomopy.recon on {num_core} cores ...') | 1442 logging.debug(f'running recon on {num_core} cores ...') |
| 1367 tomo_recon_stack = tomopy.recon(tomo_stack, thetas, centers, | 1443 tomo_recon_stack = tomopy.recon(tomo_stack, thetas, centers, |
| 1368 init_recon=tomo_recon_stack, options=options, sinogram_order=True, | 1444 init_recon=tomo_recon_stack, options=options, sinogram_order=True, |
| 1369 algorithm=tomopy.astra, ncore=num_core) | 1445 algorithm=tomopy.astra, ncore=num_core) |
| 1370 logging.info(f'... tomopy.recon took {time()-t0:.2f} seconds!') | 1446 logging.debug(f'... recon took {time()-t0:.2f} seconds!') |
| 1371 if True: | 1447 if True: |
| 1372 t0 = time() | 1448 t0 = time() |
| 1373 logging.info(f'running tomopy.misc.corr.remove_ring on {num_core} cores ...') | 1449 logging.debug(f'running remove_ring on {num_core} cores ...') |
| 1374 tomopy.misc.corr.remove_ring(tomo_recon_stack, rwidth=rwidth, out=tomo_recon_stack, | 1450 tomopy.misc.corr.remove_ring(tomo_recon_stack, rwidth=rwidth, out=tomo_recon_stack, |
| 1375 ncore=num_core) | 1451 ncore=num_core) |
| 1376 logging.info(f'... tomopy.misc.corr.remove_ring took {time()-t0:.2f} seconds!') | 1452 logging.debug(f'... remove_ring took {time()-t0:.2f} seconds!') |
| 1377 return tomo_recon_stack | 1453 return tomo_recon_stack |
| 1378 | 1454 |
| 1379 def findImageFiles(self): | 1455 def findImageFiles(self, tiff_to_h5_flag = False): |
| 1380 """Find all available image files. | 1456 """Find all available image files. |
| 1381 """ | 1457 """ |
| 1382 self.is_valid = True | 1458 self.is_valid = True |
| 1383 | 1459 |
| 1384 # Find dark field images | 1460 # Find dark field images |
| 1405 logging.error('Inconsistent image start index for dark field images') | 1481 logging.error('Inconsistent image start index for dark field images') |
| 1406 if dark_field['data_path']: | 1482 if dark_field['data_path']: |
| 1407 self.is_valid = False | 1483 self.is_valid = False |
| 1408 logging.info(f'Number of dark field images = {dark_field["num"]}') | 1484 logging.info(f'Number of dark field images = {dark_field["num"]}') |
| 1409 logging.info(f'Dark field image start index = {dark_field["img_start"]}') | 1485 logging.info(f'Dark field image start index = {dark_field["img_start"]}') |
| 1486 if num_imgs and tiff_to_h5_flag and self.config['data_filetype'] == 'tif': | |
| 1487 dark_files = msnc.combine_tiffs_in_h5(dark_files, num_imgs, | |
| 1488 f'{self.config["work_folder"]}/dark_field.h5') | |
| 1489 dark_field['data_path'] = dark_files[0] | |
| 1410 | 1490 |
| 1411 # Find bright field images | 1491 # Find bright field images |
| 1412 bright_field = self.config['bright_field'] | 1492 bright_field = self.config['bright_field'] |
| 1413 img_start, num_imgs, bright_files = msnc.findImageFiles( | 1493 img_start, num_imgs, bright_files = msnc.findImageFiles( |
| 1414 bright_field['data_path'], self.config['data_filetype'], 'bright field') | 1494 bright_field['data_path'], self.config['data_filetype'], 'bright field') |
| 1429 if img_start_old < img_start: | 1509 if img_start_old < img_start: |
| 1430 logging.warning('Inconsistent image start index for bright field images') | 1510 logging.warning('Inconsistent image start index for bright field images') |
| 1431 self.is_valid = False | 1511 self.is_valid = False |
| 1432 logging.info(f'Number of bright field images = {bright_field["num"]}') | 1512 logging.info(f'Number of bright field images = {bright_field["num"]}') |
| 1433 logging.info(f'Bright field image start index = {bright_field["img_start"]}') | 1513 logging.info(f'Bright field image start index = {bright_field["img_start"]}') |
| 1514 if num_imgs and tiff_to_h5_flag and self.config['data_filetype'] == 'tif': | |
| 1515 bright_files = msnc.combine_tiffs_in_h5(bright_files, num_imgs, | |
| 1516 f'{self.config["work_folder"]}/bright_field.h5') | |
| 1517 bright_field['data_path'] = bright_files[0] | |
| 1434 | 1518 |
| 1435 # Find tomography images | 1519 # Find tomography images |
| 1436 tomo_stack_files = [] | 1520 tomo_stack_files = [] |
| 1437 for stack in self.config['stack_info']['stacks']: | 1521 for stack in self.config['stack_info']['stacks']: |
| 1438 index = stack['index'] | 1522 index = stack['index'] |
| 1455 if img_start_old < img_start: | 1539 if img_start_old < img_start: |
| 1456 logging.warning('Inconsistent image start index for tomography images') | 1540 logging.warning('Inconsistent image start index for tomography images') |
| 1457 self.is_valid = False | 1541 self.is_valid = False |
| 1458 logging.info(f'Number of tomography images for set {index} = {stack["num"]}') | 1542 logging.info(f'Number of tomography images for set {index} = {stack["num"]}') |
| 1459 logging.info(f'Tomography set {index} image start index = {stack["img_start"]}') | 1543 logging.info(f'Tomography set {index} image start index = {stack["img_start"]}') |
| 1544 if num_imgs and tiff_to_h5_flag and self.config['data_filetype'] == 'tif': | |
| 1545 tomo_files = msnc.combine_tiffs_in_h5(tomo_files, num_imgs, | |
| 1546 f'{self.config["work_folder"]}/tomo_field_{index}.h5') | |
| 1547 stack['data_path'] = tomo_files[0] | |
| 1460 tomo_stack_files.append(tomo_files) | 1548 tomo_stack_files.append(tomo_files) |
| 1461 del tomo_files | 1549 del tomo_files |
| 1462 | 1550 |
| 1463 # Safe updated config | 1551 # Safe updated config |
| 1552 if tiff_to_h5_flag: | |
| 1553 self.config['data_filetype'] == 'h5' | |
| 1464 if self.is_valid: | 1554 if self.is_valid: |
| 1465 self.cf.saveFile(self.config_out) | 1555 self.cf.saveFile(self.config_out) |
| 1466 | 1556 |
| 1467 return dark_files, bright_files, tomo_stack_files | 1557 return dark_files, bright_files, tomo_stack_files |
| 1468 | 1558 |
| 1499 assert(isinstance(galaxy_param, dict)) | 1589 assert(isinstance(galaxy_param, dict)) |
| 1500 tdf_files = galaxy_param['tdf_files'] | 1590 tdf_files = galaxy_param['tdf_files'] |
| 1501 tbf_files = galaxy_param['tbf_files'] | 1591 tbf_files = galaxy_param['tbf_files'] |
| 1502 tomo_stack_files = galaxy_param['tomo_stack_files'] | 1592 tomo_stack_files = galaxy_param['tomo_stack_files'] |
| 1503 assert(num_tomo_stacks == len(tomo_stack_files)) | 1593 assert(num_tomo_stacks == len(tomo_stack_files)) |
| 1594 if not os.path.exists('setup_pngs'): | |
| 1595 os.mkdir('setup_pngs') | |
| 1504 else: | 1596 else: |
| 1505 if galaxy_param: | 1597 if galaxy_param: |
| 1506 logging.warning('Ignoring galaxy_param in findCenters (only for Galaxy)') | 1598 logging.warning('Ignoring galaxy_param in genTomoStacks (only for Galaxy)') |
| 1507 galaxy_param = None | 1599 galaxy_param = None |
| 1508 tdf_files, tbf_files, tomo_stack_files = self.findImageFiles() | 1600 tdf_files, tbf_files, tomo_stack_files = self.findImageFiles() |
| 1509 if not self.is_valid: | 1601 if not self.is_valid: |
| 1510 return | 1602 return |
| 1511 for i,stack in enumerate(stacks): | 1603 for i,stack in enumerate(stacks): |
| 1523 if not self.is_valid: | 1615 if not self.is_valid: |
| 1524 return | 1616 return |
| 1525 | 1617 |
| 1526 # Generate dark field | 1618 # Generate dark field |
| 1527 if tdf_files: | 1619 if tdf_files: |
| 1528 self._genDark(tdf_files, galaxy_param['dark_field_pngname']) | 1620 self._genDark(tdf_files) |
| 1529 | 1621 |
| 1530 # Generate bright field | 1622 # Generate bright field |
| 1531 self._genBright(tbf_files, galaxy_param['bright_field_pngname']) | 1623 self._genBright(tbf_files) |
| 1532 | 1624 |
| 1533 # Set vertical detector bounds for image stack | 1625 # Set vertical detector bounds for image stack |
| 1534 self._setDetectorBounds(tomo_stack_files, galaxy_param['tomo_field_pngname'], | 1626 self._setDetectorBounds(tomo_stack_files) |
| 1535 galaxy_param['detectorbounds_pngname']) | |
| 1536 | 1627 |
| 1537 # Set zoom and/or theta skip to reduce memory the requirement | 1628 # Set zoom and/or theta skip to reduce memory the requirement |
| 1538 self._setZoomOrSkip() | 1629 self._setZoomOrSkip() |
| 1539 | 1630 |
| 1540 # Generate tomography fields | 1631 # Generate tomography fields |
| 1575 logging.debug('Find centers for tomography stacks') | 1666 logging.debug('Find centers for tomography stacks') |
| 1576 stacks = self.config['stack_info']['stacks'] | 1667 stacks = self.config['stack_info']['stacks'] |
| 1577 available_stacks = [stack['index'] for stack in stacks if stack.get('preprocessed', False)] | 1668 available_stacks = [stack['index'] for stack in stacks if stack.get('preprocessed', False)] |
| 1578 logging.debug('Available stacks: {available_stacks}') | 1669 logging.debug('Available stacks: {available_stacks}') |
| 1579 if self.galaxy_flag: | 1670 if self.galaxy_flag: |
| 1580 assert(isinstance(galaxy_param, dict)) | |
| 1581 row_bounds = galaxy_param['row_bounds'] | 1671 row_bounds = galaxy_param['row_bounds'] |
| 1582 center_rows = galaxy_param['center_rows'] | 1672 center_rows = galaxy_param['center_rows'] |
| 1583 if center_rows is None: | |
| 1584 logging.error('Missing center_rows entry in galaxy_param') | |
| 1585 return | |
| 1586 center_type_selector = galaxy_param['center_type_selector'] | 1673 center_type_selector = galaxy_param['center_type_selector'] |
| 1587 if center_type_selector: | 1674 if center_type_selector: |
| 1588 if center_type_selector == 'vo': | 1675 if center_type_selector == 'vo': |
| 1589 set_center = None | 1676 set_center = None |
| 1590 elif center_type_selector == 'user': | 1677 elif center_type_selector == 'user': |
| 1636 if not center_stack.size: | 1723 if not center_stack.size: |
| 1637 stacks[0]['preprocessed'] = False | 1724 stacks[0]['preprocessed'] = False |
| 1638 raise OSError('Unable to load the required preprocessed tomography stack') | 1725 raise OSError('Unable to load the required preprocessed tomography stack') |
| 1639 assert(stacks[0].get('preprocessed', False) == True) | 1726 assert(stacks[0].get('preprocessed', False) == True) |
| 1640 elif self.galaxy_flag: | 1727 elif self.galaxy_flag: |
| 1641 logging.error('CHECK/FIX FOR GALAXY') | 1728 center_stack_index = stacks[int(num_tomo_stacks/2)]['index'] |
| 1642 #center_stack_index = stacks[int(num_tomo_stacks/2)]['index'] | 1729 tomo_stack_index = available_stacks.index(center_stack_index) |
| 1730 center_stack = self.tomo_stacks[tomo_stack_index] | |
| 1731 if not center_stack.size: | |
| 1732 stacks[tomo_stack_index]['preprocessed'] = False | |
| 1733 raise OSError('Unable to load the required preprocessed tomography stack') | |
| 1734 assert(stacks[tomo_stack_index].get('preprocessed', False) == True) | |
| 1643 else: | 1735 else: |
| 1644 while True: | 1736 while True: |
| 1645 if not center_stack_index: | 1737 if not center_stack_index: |
| 1646 center_stack_index = pyip.inputInt('\nEnter tomography stack index to get ' | 1738 center_stack_index = pyip.inputInt('\nEnter tomography stack index to get ' |
| 1647 f'rotation axis centers {available_stacks}: ') | 1739 f'rotation axis centers {available_stacks}: ') |
| 1673 row_bounds = [0, center_stack.shape[0]] | 1765 row_bounds = [0, center_stack.shape[0]] |
| 1674 if row_bounds[0] == -1: | 1766 if row_bounds[0] == -1: |
| 1675 row_bounds[0] = 0 | 1767 row_bounds[0] = 0 |
| 1676 if row_bounds[1] == -1: | 1768 if row_bounds[1] == -1: |
| 1677 row_bounds[1] = center_stack.shape[0] | 1769 row_bounds[1] = center_stack.shape[0] |
| 1770 if center_rows[0] == -1: | |
| 1771 center_rows[0] = 0 | |
| 1772 if center_rows[1] == -1: | |
| 1773 center_rows[1] = center_stack.shape[0]-1 | |
| 1678 if not msnc.is_index_range(row_bounds, 0, center_stack.shape[0]): | 1774 if not msnc.is_index_range(row_bounds, 0, center_stack.shape[0]): |
| 1679 msnc.illegal_value('row_bounds', row_bounds) | 1775 msnc.illegal_value('row_bounds', row_bounds) |
| 1680 return | 1776 return |
| 1681 | 1777 |
| 1682 # Set thetas (in degrees) | 1778 # Set thetas (in degrees) |
| 1716 title=f'center stack theta={theta_start}') | 1812 title=f'center stack theta={theta_start}') |
| 1717 else: | 1813 else: |
| 1718 n1 = row_bounds[0] | 1814 n1 = row_bounds[0] |
| 1719 n2 = row_bounds[1] | 1815 n2 = row_bounds[1] |
| 1720 else: | 1816 else: |
| 1721 logging.error('CHECK/FIX FOR GALAXY') | |
| 1722 tomo_ref_heights = [stack['ref_height'] for stack in stacks] | 1817 tomo_ref_heights = [stack['ref_height'] for stack in stacks] |
| 1723 n1 = int((1.+(tomo_ref_heights[0]+center_stack.shape[0]*eff_pixel_size- | 1818 n1 = int((1.+(tomo_ref_heights[0]+center_stack.shape[0]*eff_pixel_size- |
| 1724 tomo_ref_heights[1])/eff_pixel_size)/2) | 1819 tomo_ref_heights[1])/eff_pixel_size)/2) |
| 1725 n2 = center_stack.shape[0]-n1 | 1820 n2 = center_stack.shape[0]-n1 |
| 1726 logging.debug(f'n1 = {n1}, n2 = {n2} (n2-n1) = {(n2-n1)*eff_pixel_size:.3f} mm') | 1821 logging.debug(f'n1 = {n1}, n2 = {n2} (n2-n1) = {(n2-n1)*eff_pixel_size:.3f} mm') |
| 1727 if not center_stack.size: | |
| 1728 RuntimeError('Center stack not loaded') | |
| 1729 if not self.test_mode and not self.galaxy_flag: | 1822 if not self.test_mode and not self.galaxy_flag: |
| 1730 tmp = center_stack[:,0,:] | 1823 tmp = center_stack[:,0,:] |
| 1731 tmp_max = tmp.max() | 1824 tmp_max = tmp.max() |
| 1732 tmp[n1,:] = tmp_max | 1825 tmp[n1,:] = tmp_max |
| 1733 tmp[n2-1,:] = tmp_max | 1826 tmp[n2-1,:] = tmp_max |
| 1916 def reconstructTomoStacks(self, galaxy_param=None, num_core=None): | 2009 def reconstructTomoStacks(self, galaxy_param=None, num_core=None): |
| 1917 """Reconstruct tomography stacks. | 2010 """Reconstruct tomography stacks. |
| 1918 """ | 2011 """ |
| 1919 if num_core is None: | 2012 if num_core is None: |
| 1920 num_core = self.num_core | 2013 num_core = self.num_core |
| 1921 logging.info(f'num_core available = {num_core}') | 2014 logging.info(f'num_core = {num_core}') |
| 1922 #if num_core > 24: | |
| 1923 # num_core = 24 | |
| 1924 logging.info(f'num_core used = {num_core}') | |
| 1925 if self.galaxy_flag: | 2015 if self.galaxy_flag: |
| 1926 assert(galaxy_param) | 2016 assert(galaxy_param) |
| 1927 if not os.path.exists('center_slice_pngs'): | 2017 if not os.path.exists('center_slice_pngs'): |
| 1928 os.mkdir('center_slice_pngs') | 2018 os.mkdir('center_slice_pngs') |
| 1929 logging.debug('Reconstruct tomography stacks') | 2019 logging.debug('Reconstruct tomography stacks') |
| 2014 continue | 2104 continue |
| 2015 assert(0 <= lower_row < upper_row < self.tomo_stacks[i].shape[0]) | 2105 assert(0 <= lower_row < upper_row < self.tomo_stacks[i].shape[0]) |
| 2016 center_offsets = [lower_center_offset-lower_row*center_slope, | 2106 center_offsets = [lower_center_offset-lower_row*center_slope, |
| 2017 upper_center_offset+(self.tomo_stacks[i].shape[0]-1-upper_row)*center_slope] | 2107 upper_center_offset+(self.tomo_stacks[i].shape[0]-1-upper_row)*center_slope] |
| 2018 t0 = time() | 2108 t0 = time() |
| 2019 logging.info(f'running self._reconstructOneTomoStack on {num_core} cores ...') | 2109 logging.debug(f'running _reconstructOneTomoStack on {num_core} cores ...') |
| 2020 self.tomo_recon_stacks[i]= self._reconstructOneTomoStack(self.tomo_stacks[i], | 2110 self.tomo_recon_stacks[i]= self._reconstructOneTomoStack(self.tomo_stacks[i], |
| 2021 thetas, center_offsets=center_offsets, sigma=0.1, num_core=num_core, | 2111 thetas, center_offsets=center_offsets, sigma=0.1, num_core=num_core, |
| 2022 algorithm='gridrec', run_secondary_sirt=True, secondary_iter=25) | 2112 algorithm='gridrec', run_secondary_sirt=True, secondary_iter=25) |
| 2023 logging.info(f'... self._reconstructOneTomoStack took {time()-t0:.2f} seconds!') | 2113 logging.debug(f'... _reconstructOneTomoStack took {time()-t0:.2f} seconds!') |
| 2024 #logging.info(f'Reconstruction of stack {index} took {time()-t0:.2f} seconds!') | 2114 logging.info(f'Reconstruction of stack {index} took {time()-t0:.2f} seconds!') |
| 2025 if self.galaxy_flag: | 2115 if self.galaxy_flag: |
| 2026 x_slice = int(self.tomo_stacks[i].shape[0]/2) | 2116 x_slice = int(self.tomo_stacks[i].shape[0]/2) |
| 2027 title = f'{basetitle} {index} xslice{x_slice}' | 2117 title = f'{basetitle} {index} xslice{x_slice}' |
| 2028 msnc.quickImshow(self.tomo_recon_stacks[i][x_slice,:,:], title=title, | 2118 msnc.quickImshow(self.tomo_recon_stacks[i][x_slice,:,:], title=title, |
| 2029 path='center_slice_pngs', save_fig=True, save_only=True) | 2119 path='center_slice_pngs', save_fig=True, save_only=True) |
| 2219 z_bounds = [0, tomo_recon_combined.shape[0]] | 2309 z_bounds = [0, tomo_recon_combined.shape[0]] |
| 2220 else: | 2310 else: |
| 2221 z_bounds = msnc.selectArrayBounds(tomosum, title='recon combined sum xy') | 2311 z_bounds = msnc.selectArrayBounds(tomosum, title='recon combined sum xy') |
| 2222 if z_bounds[0] != 0 or z_bounds[1] != tomo_recon_combined.shape[0]: | 2312 if z_bounds[0] != 0 or z_bounds[1] != tomo_recon_combined.shape[0]: |
| 2223 tomo_recon_combined = tomo_recon_combined[z_bounds[0]:z_bounds[1],:,:] | 2313 tomo_recon_combined = tomo_recon_combined[z_bounds[0]:z_bounds[1],:,:] |
| 2224 logging.info(f'tomo_recon_combined.shape = {tomo_recon_combined.shape}') | |
| 2225 if self.save_plots_only: | 2314 if self.save_plots_only: |
| 2226 msnc.clearFig('recon combined sum xy') | 2315 msnc.clearFig('recon combined sum xy') |
| 2227 | 2316 |
| 2228 # Plot center slices | 2317 # Plot center slices |
| 2229 msnc.quickImshow(tomo_recon_combined[int(tomo_recon_combined.shape[0]/2),:,:], | 2318 msnc.quickImshow(tomo_recon_combined[int(tomo_recon_combined.shape[0]/2),:,:], |
