Ejemplo n.º 1
0
    def full(images: Images,
             cors: List[ScalarCoR],
             recon_params: ReconstructionParameters,
             progress: Optional[Progress] = None) -> Images:
        progress = Progress.ensure_instance(progress, num_steps=images.height)
        output_shape = (images.num_sinograms, images.width, images.width)
        output_images: Images = Images.create_empty_images(
            output_shape, images.dtype, images.metadata)
        output_images.record_operation('AstraRecon.full', 'Reconstruction',
                                       **recon_params.to_dict())

        # FIXME multiple GPU support - just starting up a Pool doesn't seem to work
        # the GPUs can't initialise the memory properly. Not sure why
        # num_gpus = AstraRecon._count_gpus()
        # LOG.info(f"Running with {num_gpus} GPUs")
        # partial = ptsm.create_partial(AstraRecon.single, ptsm.fwd_gpu_recon,
        #                               num_gpus=num_gpus, cors=cors,
        #                               proj_angles=proj_angles, recon_params=recon_params)
        # ptsm.execute(images.sinograms, output_images.data, partial, num_gpus, progress=progress)

        proj_angles = images.projection_angles()
        for i in range(images.height):
            output_images.data[i] = AstraRecon.single_sino(
                images.sino(i), cors[i], proj_angles, recon_params)
            progress.update(1, "Reconstructed slice")

        return output_images
Ejemplo n.º 2
0
 def find_cor(images: Images, slice_idx: int, start_cor: float,
              recon_params: ReconstructionParameters) -> float:
     return tomopy.find_center(images.sinograms,
                               images.projection_angles(
                                   recon_params.max_projection_angle).value,
                               ind=slice_idx,
                               init=start_cor,
                               sinogram_order=True)
Ejemplo n.º 3
0
    def __init__(self, images: Images, slice_idx: int, initial_cor: ScalarCoR,
                 recon_params: ReconstructionParameters):
        self.image_width = images.width
        self.sino = images.sino(slice_idx)

        # Initial parameters
        self.centre_cor = initial_cor.value
        self.cor_step = 50

        # Cache projection angles
        self.proj_angles = images.projection_angles()
        self.recon_params = recon_params
        self.reconstructor = get_reconstructor_for(recon_params.algorithm)
Ejemplo n.º 4
0
    def full(images: Images,
             cors: List[ScalarCoR],
             recon_params: ReconstructionParameters,
             progress: Optional[Progress] = None) -> Images:
        progress = Progress.ensure_instance(progress, num_steps=images.height)
        output_shape = (images.num_sinograms, images.width, images.width)
        output_images: Images = Images.create_empty_images(
            output_shape, images.dtype, images.metadata)
        output_images.record_operation('AstraRecon.full', 'Reconstruction',
                                       **recon_params.to_dict())

        proj_angles = images.projection_angles(
            recon_params.max_projection_angle)
        for i in range(images.height):
            output_images.data[i] = AstraRecon.single_sino(
                images.sino(i), cors[i], proj_angles, recon_params)
            progress.update(1, "Reconstructed slice")

        return output_images
Ejemplo n.º 5
0
    def find_cor(images: Images, slice_idx: int, start_cor: float,
                 recon_params: ReconstructionParameters) -> float:
        """
        Find the best CoR for this slice by maximising the squared sum of the reconstructed slice.

        Larger squared sum -> bigger deviance from the mean, i.e. larger distance between noise and data
        """

        proj_angles = images.projection_angles()

        def get_sumsq(image: np.ndarray) -> float:
            return np.sum(image**2)

        def minimizer_function(cor):
            return -get_sumsq(
                AstraRecon.single_sino(images.sino(slice_idx), ScalarCoR(cor),
                                       proj_angles, recon_params))

        return minimize(minimizer_function,
                        start_cor,
                        method='nelder-mead',
                        tol=0.1).x[0]
Ejemplo n.º 6
0
    def __init__(self, images: Images, slice_idx: int, initial_cor: ScalarCoR, recon_params: ReconstructionParameters,
                 iters_mode: bool):
        self.image_width = images.width
        self.sino = images.sino(slice_idx)

        # Initial parameters
        if iters_mode:
            self.centre_value: Union[int, float] = INIT_ITERS_CENTRE_VALUE
            self.step = INIT_ITERS_STEP
            self.initial_cor = initial_cor
            self._recon_preview = self._recon_iters_preview
            self._divide_step = self._divide_iters_step
        else:
            self.centre_value = initial_cor.value
            self.step = self.image_width * 0.05
            self._recon_preview = self._recon_cor_preview
            self._divide_step = self._divide_cor_step

        # Cache projection angles
        self.proj_angles = images.projection_angles(recon_params.max_projection_angle)
        self.recon_params = recon_params
        self.reconstructor = get_reconstructor_for(recon_params.algorithm)
Ejemplo n.º 7
0
    def full(images: Images,
             cors: List[ScalarCoR],
             recon_params: ReconstructionParameters,
             progress: Optional[Progress] = None):
        """
        Performs a volume reconstruction using sample data provided as sinograms.

        :param images: Array of sinogram images
        :param cors: Array of centre of rotation values
        :param proj_angles: Array of projection angles
        :param recon_params: Reconstruction Parameters
        :param progress: Optional progress reporter
        :return: 3D image data for reconstructed volume
        """
        progress = Progress.ensure_instance(progress,
                                            task_name='TomoPy reconstruction')

        import multiprocessing
        ncores = multiprocessing.cpu_count()

        kwargs = {
            'ncore': ncores,
            'tomo': BaseRecon.prepare_sinogram(images.data, recon_params),
            'sinogram_order': images._is_sinograms,
            'theta':
            images.projection_angles(recon_params.max_projection_angle).value,
            'center': [cor.value for cor in cors],
            'algorithm': recon_params.algorithm,
            'filter_name': recon_params.filter_name
        }

        with progress:
            volume = tomopy.recon(**kwargs)
            LOG.info('Reconstructed 3D volume with shape: {0}'.format(
                volume.shape))

        return Images(volume)
Ejemplo n.º 8
0
    def full(images: Images,
             cors: List[ScalarCoR],
             recon_params: ReconstructionParameters,
             progress: Optional[Progress] = None):
        """
        Performs a volume reconstruction using sample data provided as sinograms.

        :param images: Array of sinogram images
        :param cors: Array of centre of rotation values
        :param proj_angles: Array of projection angles in radians
        :param recon_params: Reconstruction Parameters
        :param progress: Optional progress reporter
        :return: 3D image data for reconstructed volume
        """

        progress = Progress.ensure_instance(progress,
                                            task_name='CIL reconstruction',
                                            num_steps=recon_params.num_iter +
                                            1)

        projection_size = full_size_KB(images.data.shape, images.dtype)
        recon_volume_shape = images.data.shape[2], images.data.shape[
            2], images.data.shape[1]
        recon_volume_size = full_size_KB(recon_volume_shape, images.dtype)
        estimated_mem_required = 5 * projection_size + 13 * recon_volume_size
        free_mem = system_free_memory().kb()

        if (estimated_mem_required > free_mem):
            estimate_gb = estimated_mem_required / 1024 / 1024
            raise RuntimeError(
                "The machine does not have enough physical memory available to allocate space for this data."
                f" Estimated RAM needed is {estimate_gb:.2f} GB")

        if cil_mutex.locked():
            LOG.warning("CIL recon already in progress")

        with cil_mutex:
            progress.update(steps=1,
                            msg='CIL: Setting up reconstruction',
                            force_continue=False)
            angles = images.projection_angles(
                recon_params.max_projection_angle).value
            shape = images.data.shape
            pixel_num_h, pixel_num_v = shape[2], shape[1]
            pixel_size = 1.
            if recon_params.tilt is None:
                raise ValueError("recon_params.tilt is not set")
            rot_pos = [
                (cors[pixel_num_v // 2].value - pixel_num_h / 2) * pixel_size,
                0, 0
            ]
            slope = -np.tan(np.deg2rad(recon_params.tilt.value))
            rot_angle = [slope, 0, 1]

            ag = AcquisitionGeometry.create_Parallel3D(
                rotation_axis_position=rot_pos,
                rotation_axis_direction=rot_angle)
            ag.set_panel([pixel_num_h, pixel_num_v],
                         pixel_size=(pixel_size, pixel_size))
            ag.set_angles(angles=angles, angle_unit='radian')
            ag.set_labels(DataOrder.TIGRE_AG_LABELS)

            # stick it into an AcquisitionData
            data = ag.allocate(None)
            data.fill(BaseRecon.prepare_sinogram(images.data, recon_params))
            data.reorder('astra')

            alpha = recon_params.alpha

            ig = ag.get_ImageGeometry()
            # set up TV regularisation
            K, f1, f2, G = CILRecon.set_up_TV_regularisation(ig, data, alpha)

            # alpha = 1.0
            # f1 =  alpha * MixedL21Norm()
            # f2 = 0.5 * L2NormSquared(b=ad2d)
            F = BlockFunction(f1, f2)
            normK = K.norm()
            sigma = 1
            tau = 1 / (sigma * normK**2)

            pdhg = PDHG(f=F,
                        g=G,
                        operator=K,
                        tau=tau,
                        sigma=sigma,
                        max_iteration=100000,
                        update_objective_interval=10)

            with progress:
                for iter in range(recon_params.num_iter):
                    progress.update(
                        steps=1,
                        msg=
                        f'CIL: Iteration {iter+1} of {recon_params.num_iter}:'
                        f'Objective {pdhg.get_last_objective():.2f}',
                        force_continue=False)
                    pdhg.next()
                volume = pdhg.solution.as_array()
                LOG.info('Reconstructed 3D volume with shape: {0}'.format(
                    volume.shape))
            return Images(volume)