def do_recon(self, cfg, cmd_line=None):
        """
        Run a reconstruction using a particular tool, algorithm and setup

        @param preproc_cfg :: configuration (pre-processing + tool+algorithm + post-processing)

        @param cmd_line :: command line text if running from the CLI. When provided it will
        be written in the output readme file(s) for reference.
        """
        if not cfg or not isinstance(cfg, tomocfg.ReconstructionConfig):
            raise ValueError("Cannot run a reconstruction without a valid configuration")

        if not cfg.preproc_cfg.input_dir:
            raise ValueError("Cannot run a reconstruction without setting the input path")

        if not cfg.postproc_cfg.output_dir:
            raise ValueError("Cannot run a reconstruction without setting the output path")

        readme_fullpath = os.path.join(cfg.postproc_cfg.output_dir, self._OUT_README_FNAME)
        tstart = self.gen_readme_summary_begin(readme_fullpath, cfg, cmd_line)

        data, white, dark = self.read_in_stack(cfg.preproc_cfg.input_dir, cfg.preproc_cfg.in_img_format,
                                               cfg.preproc_cfg.input_dir_flat, cfg.preproc_cfg.input_dir_dark)
        print "Shape of raw data: {0}, dtype: {1}".format(data.shape, data.dtype)

        # These imports will raise appropriate exceptions in case of error
        import tomorec.tool_imports as tti
        if 'astra' == cfg.alg_cfg.tool:
            tti.import_tomo_tool('astra')
        elif 'tomopy' == cfg.alg_cfg.tool:
            tti.import_tomo_tool('tomopy')

        preproc_data = self.apply_all_preproc(data, cfg.preproc_cfg, white, dark)
        print "Shape of pre-processed data: {0}, dtype: {1}".format(preproc_data.shape, data.dtype)

        # Save pre-proc images
        self.save_preproc_images(cfg.postproc_cfg.output_dir, preproc_data, cfg.preproc_cfg)

        # Reconstruction
        t_recon_start = time.time()
        recon_data = self.run_reconstruct_3d(preproc_data, cfg.preproc_cfg, cfg.alg_cfg)
        t_recon_end = time.time()
        print("Reconstructed volume. Shape: {0}, and pixel data type: {1}".
              format(recon_data.shape, recon_data.dtype))

        # Post-processing
        self.apply_postproc_filters(recon_data, cfg.postproc_cfg)

        # Save output from the reconstruction
        self.save_recon_output(recon_data, cfg, save_netcdf_vol=True)

        self.gen_readme_summary_end(readme_fullpath, (data, preproc_data, recon_data), tstart,
                                    t_recon_end - t_recon_start)

        print "Finished reconstruction."
    def run_reconstruct_3d(self, proj_data, preproc_cfg, alg_cfg):
        """
        A 3D reconstruction

        @param proj_data :: Input projected images
        @param tool :: reconstruction tool to call/use

        Returns :: reconstructed volume
        """
        self._check_data_stack(proj_data)

        num_proj = proj_data.shape[0]
        inc = float(preproc_cfg.max_angle)/(num_proj-1)

        proj_angles=np.arange(0, num_proj*inc, inc)
        # For tomopy
        proj_angles = np.radians(proj_angles)

        verbosity = 1
        if 'astra' == alg_cfg.tool:
            #run_reconstruct_3d_astra(proj_data, algorithm, cor, proj_angles=proj_angles)
            return run_reconstruct_3d_astra_simple(proj_data, proj_angles, alg_cfg, preproc_cfg.cor)

        for slice_idx in [200]: # examples to check: [30, 130, 230, 330, 430]:
            print " > Finding center with tomopy find_center, slice_idx: {0}...".format(slice_idx)
            import tomorec.tool_imports as tti
            try:
                tomopy = tti.import_tomo_tool('tomopy')
                tomopy_cor = tomopy.find_center(tomo=proj_data, theta=proj_angles, ind=slice_idx, emission=False)
                if not preproc_cfg.cor:
                    preproc_cfg.cor = tomopy_cor
                print " > Center of rotation found by tomopy.find_center:  {0}".format(tomopy_cor)
            except ImportError as exc:
                print(" * WARNING: could not import tomopy so could not use the tomopy method to find the center "
                      "of rotation. Details: {0}".format(exc))


        print "Using center of rotation: {0}".format(preproc_cfg.cor)
        start = time.time()
        if 'tomopy' == alg_cfg.tool and 'gridrec' != alg_cfg.algorithm and 'fbp' != alg_cfg.algorithm:
            if not alg_cfg.num_iter:
                alg.cfg_num_iter = tomocfg.PreProcConfig.DEF_NUM_ITER
            # For ref, some typical run times with 4 cores:
            # 'bart' with num_iter=20 => 467.640s ~= 7.8m
            # 'sirt' with num_iter=30 => 698.119 ~= 11.63
            if verbosity >= 1:
                print("Running iterative method with tomopy. Algorithm: {0}, "
                      "number of iterations: {1}".format(algorithm, alg_cfg.num_iter))
            rec = tomopy.recon(tomo=proj_data, theta=proj_angles, center=cor,
                               algorithm=alg_cfg.algorithm, num_iter=alg_cfg.num_iter) #, filter_name='parzen')
        else:
            if verbosity >= 1:
                print("Running non-iterative reconstruction algorithm with tomopy. "
                      "Algorithm: {0}".format(alg_cfg.algorithm))
            rec = tomopy.recon(tomo=proj_data, theta=proj_angles, center=preproc_cfg.cor,
                               algorithm=alg_cfg.algorithm)
        tnow = time.time()
        print "Reconstructed 3D volume. Time elapsed in reconstruction algorithm: {0:.3f}".format(tnow - start)

        return rec
Example #3
0
    def run_reconstruct_3d_astra_simple(self,
                                        proj_data,
                                        proj_angles,
                                        alg_cfg,
                                        cor=None):
        """
        Run a reconstruction with astra, simple handling of projected data/images

        @param proj_data :: projection images
        @param alg_cfg :: tool/algorithm configuration
        @param cor :: center of rotation
        @param proj_angles :: angles corresponding to the projection images
        """
        import tomorec.tool_imports as tti
        astra = tti.import_tomo_tool('astra')
        sinograms = proj_data

        sinograms = np.swapaxes(sinograms, 0, 1)

        plow = (proj_data.shape[2] - cor * 2)
        phigh = 0

        # minval = np.amin(sinograms)
        sinograms = np.pad(sinograms, ((0, 0), (0, 0), (plow, phigh)),
                           mode='reflect')

        proj_geom = astra.create_proj_geom('parallel3d', .0, 1.0,
                                           proj_data.shape[1],
                                           sinograms.shape[2], proj_angles)
        sinogram_id = astra.data3d.create('-sino', proj_geom, sinograms)

        vol_geom = astra.create_vol_geom(proj_data.shape[1],
                                         sinograms.shape[2],
                                         proj_data.shape[1])
        recon_id = astra.data3d.create('-vol', vol_geom)
        alg_cfg = astra.astra_dict(alg_cfg.algorithm)
        alg_cfg['ReconstructionDataId'] = recon_id
        alg_cfg['ProjectionDataId'] = sinogram_id
        alg_id = astra.algorithm.create(alg_cfg)

        number_of_iters = 100
        astra.algorithm.run(alg_id, number_of_iters)
        recon = astra.data3d.get(recon_id)

        astra.algorithm.delete(alg_id)
        astra.data3d.delete(recon_id)
        astra.data3d.delete(sinogram_id)

        return recon
    def run_reconstruct_3d_astra_simple(self, proj_data, proj_angles, alg_cfg, cor=None):
        """
        Run a reconstruction with astra, simple handling of projected data/images

        @param proj_data :: projection images
        @param alg_cfg :: tool/algorithm configuration
        @param cor :: center of rotation
        @param proj_angles :: angles corresponding to the projection images
        """
        import tomorec.tool_imports as tti
        astra = tti.import_tomo_tool('astra')
        sinograms = proj_data

        sinograms = np.swapaxes(sinograms, 0, 1)

        plow = (proj_data.shape[2] - cor*2)
        phigh = 0

        # minval = np.amin(sinograms)
        sinograms = np.pad(sinograms, ((0,0),(0,0),(plow,phigh)), mode='reflect')

        proj_geom = astra.create_proj_geom('parallel3d', .0, 1.0, proj_data.shape[1],
                                           sinograms.shape[2], proj_angles)
        sinogram_id = astra.data3d.create('-sino', proj_geom, sinograms)

        vol_geom = astra.create_vol_geom(proj_data.shape[1], sinograms.shape[2], proj_data.shape[1])
        recon_id = astra.data3d.create('-vol', vol_geom)
        alg_cfg = astra.astra_dict(alg_cfg.algorithm)
        alg_cfg['ReconstructionDataId'] = recon_id
        alg_cfg['ProjectionDataId'] = sinogram_id
        alg_id = astra.algorithm.create(alg_cfg)

        number_of_iters=100
        astra.algorithm.run(alg_id, number_of_iters)
        recon = astra.data3d.get(recon_id)

        astra.algorithm.delete(alg_id)
        astra.data3d.delete(recon_id)
        astra.data3d.delete(sinogram_id)

        return recon