Beispiel #1
0
def _find_rotation_axis(params):

    log.info("  *** calculating automatic center")
    data_size = file_io.get_dx_dims(params)
    ssino = int(data_size[1] * params.nsino)

    # Select sinogram range to reconstruct
    sino_start = ssino
    sino_end = sino_start + pow(2, int(params.binning))

    sino = (int(sino_start), int(sino_end))

    # Read APS 32-BM raw data
    proj, flat, dark, theta, params_rotation_axis_ignored = file_io.read_tomo(
        sino, params)

    # apply all preprocessing functions
    data = prep.all(proj, flat, dark, params, sino)

    # find rotation center
    log.info("  *** find_center vo")
    rot_center = tomopy.find_center_vo(data)
    log.info("  *** automatic center: %f" % rot_center)

    return rot_center * np.power(2, float(params.binning))
Beispiel #2
0
def _find_rotation_axis(params):
    log.info("  *** calculating automatic center")
    data_size = file_io.get_dx_dims(params)
    ssino = int(data_size[1] * params.nsino)
    params = file_io.read_pixel_size(params)
    params = file_io.read_filter_materials(params)
    params = file_io.read_scintillator(params)
    params = file_io.read_bright_ratio(params)

    # Select sinogram range to reconstruct
    sino_start = ssino
    sino_end = sino_start + pow(2, int(params.binning)) 

    sino = (int(sino_start), int(sino_end))

    # Read APS 32-BM raw data
    proj, flat, dark, theta, params_rotation_axis_ignored = file_io.read_tomo(sino, params, True)
        
    # apply all preprocessing functions
    data = prep.all(proj, flat, dark, params, sino)

    # if flip and stitch, just use the overlapped part of the dataset
    if params.file_type == 'flip_and_stich':
        params = _find_rotation_axis_flip_stitch(data, params)
    else:        
        # find rotation center
        log.info("  *** find_center vo")
        # if we start at 0 and end at 180, remove last angle
        if np.isclose(theta[-1] - theta[0], np.pi, 1e-4):
            data = data[:-1,...]
        params.rotation_axis = tomopy.find_center_vo(data) * np.power(2, float(params.binning))
        params.rotation_axis_flip = -1
    log.info("  *** automatic center: %f" % params.rotation_axis)
    return params
def rec(params):

    data_shape = file_io.get_dx_dims(params)

    if params.rotation_axis < 0:
        params.rotation_axis = data_shape[2] / 2

    # Select sinogram range to reconstruct
    if (params.reconstruction_type == "full"):
        nSino_per_chunk = params.nsino_per_chunk
        chunks = int(np.ceil(data_shape[1] / nSino_per_chunk))
        sino_start = 0
        sino_end = chunks * nSino_per_chunk

    else:  # "slice" and "try"
        nSino_per_chunk = pow(2, int(params.binning))
        chunks = 1
        ssino = int(data_shape[1] * params.nsino)
        sino_start = ssino
        sino_end = sino_start + pow(2, int(params.binning))


    log.info("reconstructing [%d] slices from slice [%d] to [%d] in [%d] chunks of [%d] slices each" % \
               ((sino_end - sino_start)/pow(2, int(params.binning)), sino_start/pow(2, int(params.binning)), sino_end/pow(2, int(params.binning)), \
               chunks, nSino_per_chunk/pow(2, int(params.binning))))

    strt = 0
    for iChunk in range(0, chunks):
        log.info('chunk # %i/%i' % (iChunk, chunks))
        sino_chunk_start = np.int(sino_start + nSino_per_chunk * iChunk)
        sino_chunk_end = np.int(sino_start + nSino_per_chunk * (iChunk + 1))
        log.info('  *** [%i, %i]' %
                 (sino_chunk_start / pow(2, int(params.binning)),
                  sino_chunk_end / pow(2, int(params.binning))))

        if sino_chunk_end > sino_end:
            break

        sino = (int(sino_chunk_start), int(sino_chunk_end))

        # Read APS 32-BM raw data.
        proj, flat, dark, theta, rotation_axis = file_io.read_tomo(
            sino, params)

        # apply all preprocessing functions
        data = prep.all(proj, flat, dark, params)

        # Reconstruct
        if (params.reconstruction_type == "try"):
            # try passes an array of rotation centers and this is only supported by gridrec
            reconstruction_algorithm_org = params.reconstruction_algorithm
            params.reconstruction_algorithm = 'gridrec'

            center_search_width = params.center_search_width / np.power(
                2, float(params.binning))
            center_range = (rotation_axis - center_search_width,
                            rotation_axis + center_search_width, 0.5)
            stack = np.empty(
                (len(np.arange(*center_range)), data_shape[0],
                 int(data_shape[2] / np.power(2, float(params.binning)))))
            index = 0
            for axis in np.arange(*center_range):
                stack[index] = data[:, 0, :]
                index = index + 1
            log.warning(
                '  reconstruct slice [%d] with rotation axis range [%.2f - %.2f] in [%.2f] pixel steps'
                % (ssino, center_range[0], center_range[1], center_range[2]))

            rotation_axis = np.arange(*center_range)
            rec = padded_rec(stack, theta, rotation_axis, params)

            # Save images to a temporary folder.
            fname = os.path.dirname(
                params.hdf_file
            ) + '_rec' + os.sep + 'try_center' + os.sep + file_io.path_base_name(
                params.hdf_file) + os.sep + 'recon_'
            index = 0
            for axis in np.arange(*center_range):
                rfname = fname + str('{0:.2f}'.format(
                    axis * np.power(2, float(params.binning))) + '.tiff')
                dxchange.write_tiff(rec[index], fname=rfname, overwrite=True)
                index = index + 1

            # restore original method
            params.reconstruction_algorithm = reconstruction_algorithm_org

        else:  # "slice" and "full"
            rec = padded_rec(data, theta, rotation_axis, params)

            # handling of the last chunk
            if (params.reconstruction_type == "full"):
                if (iChunk == chunks - 1):
                    log.info("handling of the last chunk")
                    log.info("  *** chunk # %d" % (chunks))
                    log.info("  *** last rec size %d" %
                             ((data_shape[1] -
                               (chunks - 1) * nSino_per_chunk) /
                              pow(2, int(params.binning))))
                    rec = rec[0:data_shape[1] -
                              (chunks - 1) * nSino_per_chunk, :, :]

            # Save images
            if (params.reconstruction_type == "full"):
                tail = os.sep + os.path.splitext(
                    os.path.basename(params.hdf_file))[0] + '_rec' + os.sep
                fname = os.path.dirname(
                    params.hdf_file) + '_rec' + tail + 'recon'
                dxchange.write_tiff_stack(rec, fname=fname, start=strt)
                strt += int(
                    (sino[1] - sino[0]) / np.power(2, float(params.binning)))
            if (params.reconstruction_type == "slice"):
                fname = os.path.dirname(
                    params.hdf_file
                ) + os.sep + 'slice_rec/recon_' + os.path.splitext(
                    os.path.basename(params.hdf_file))[0]
                dxchange.write_tiff_stack(rec, fname=fname, overwrite=False)

        log.info("  *** reconstructions: %s" % fname)
Beispiel #4
0
def rec(params):

    data_shape = file_io.get_dx_dims(params)

    #Read parameters from DXchange file if requested
    params = file_io.auto_read_dxchange(params)
    if params.rotation_axis <= 0:
        params.rotation_axis = data_shape[2] / 2
        log.warning(
            '  *** *** No rotation center given: assuming the middle of the projections at %f'
            % float(params.rotation_axis))

    # Select sinogram range to reconstruct
    if (params.reconstruction_type == "full"):
        if params.start_row:
            sino_start = params.start_row
        else:
            sino_start = 0
        if params.end_row < 0:
            sino_end = data_shape[1]
        else:
            sino_end = params.end_row
        #If params.nsino_per_chunk < 1, use # of processor cores
        if params.nsino_per_chunk < 1:
            params.nsino_per_chunk = cpu_count()
        nSino_per_chunk = params.nsino_per_chunk
        chunks = int(np.ceil((sino_end - sino_start) / nSino_per_chunk))

    else:  # "slice" and "try"
        nSino_per_chunk = pow(2, int(params.binning))
        chunks = 1
        ssino = int(data_shape[1] * params.nsino)
        sino_start = ssino
        sino_end = sino_start + pow(2, int(params.binning))

    log.info("reconstructing [%d] slices from slice [%d] to [%d] in [%d] chunks of [%d] slices each" % \
               ((sino_end - sino_start)/pow(2, int(params.binning)), sino_start/pow(2, int(params.binning)), sino_end/pow(2, int(params.binning)), \
               chunks, nSino_per_chunk/pow(2, int(params.binning))))

    strt = sino_start
    for iChunk in range(0, chunks):
        log.info('chunk # %i/%i' % (iChunk + 1, chunks))
        sino_chunk_start = np.int(sino_start + nSino_per_chunk * iChunk)
        sino_chunk_end = np.int(sino_start + nSino_per_chunk * (iChunk + 1))
        if sino_chunk_end > sino_end:
            log.warning(
                '  *** asking to go to row {0:d}, but our end row is {1:d}'.
                format(sino_chunk_end, sino_end))
            sino_chunk_end = sino_end
        log.info('  *** [%i, %i]' %
                 (sino_chunk_start / pow(2, int(params.binning)),
                  sino_chunk_end / pow(2, int(params.binning))))

        sino = (int(sino_chunk_start), int(sino_chunk_end))

        # Read APS 32-BM raw data.
        proj, flat, dark, theta, rotation_axis = file_io.read_tomo(
            sino, params)

        # What if sino overruns the size of data?
        if sino[1] - sino[0] > proj.shape[1]:
            log.warning(" *** Chunk size > remaining data size.")
            sino = (sino[0], sino[0] + proj.shape[1])

        # apply all preprocessing functions
        data = prep.all(proj, flat, dark, params, sino)

        # Reconstruct
        if (params.reconstruction_type == "try"):
            # try passes an array of rotation centers and this is only supported by gridrec
            reconstruction_algorithm_org = params.reconstruction_algorithm
            params.reconstruction_algorithm = 'gridrec'

            center_search_width = params.center_search_width / np.power(
                2, float(params.binning))
            center_range = (rotation_axis - center_search_width,
                            rotation_axis + center_search_width, 0.5)
            stack = np.empty(
                (len(np.arange(*center_range)), data_shape[0],
                 int(data_shape[2] / np.power(2, float(params.binning)))))
            index = 0
            for axis in np.arange(*center_range):
                stack[index] = data[:, 0, :]
                index = index + 1
            log.warning(
                '  reconstruct slice [%d] with rotation axis range [%.2f - %.2f] in [%.2f] pixel steps'
                % (ssino, center_range[0], center_range[1], center_range[2]))

            rotation_axis = np.arange(*center_range)
            rec = padded_rec(stack, theta, rotation_axis, params)

            # Save images to a temporary folder.
            fname = os.path.dirname(
                params.file_name
            ) + '_rec' + os.sep + 'try_center' + os.sep + file_io.path_base_name(
                params.file_name) + os.sep + 'recon_'
            index = 0
            for axis in np.arange(*center_range):
                rfname = fname + str('{0:.2f}'.format(
                    axis * np.power(2, float(params.binning))) + '.tiff')
                dxchange.write_tiff(rec[index], fname=rfname, overwrite=True)
                index = index + 1

            # restore original method
            params.reconstruction_algorithm = reconstruction_algorithm_org

        else:  # "slice" and "full"
            rec = padded_rec(data, theta, rotation_axis, params)
            # Save images
            if (params.reconstruction_type == "full"):
                tail = os.sep + os.path.splitext(
                    os.path.basename(params.file_name))[0] + '_rec' + os.sep
                fname = os.path.dirname(
                    params.file_name) + '_rec' + tail + 'recon'
                write_thread = threading.Thread(
                    target=dxchange.write_tiff_stack,
                    args=(rec, ),
                    kwargs={
                        'fname': fname,
                        'start': strt,
                        'overwrite': True
                    })
                write_thread.start()
                #dxchange.write_tiff_stack(rec, fname=fname, start=strt)
                strt += int(
                    (sino[1] - sino[0]) / np.power(2, float(params.binning)))
            if (params.reconstruction_type == "slice"):
                fname = Path.joinpath(
                    Path(os.path.dirname(params.file_name) + '_rec'),
                    'slice_rec', 'recon_' + Path(params.file_name).stem)
                # fname = Path.joinpath(Path(params.file_name).parent, 'slice_rec','recon_'+str(Path(params.file_name).stem))
                dxchange.write_tiff_stack(rec,
                                          fname=str(fname),
                                          overwrite=False)

        log.info("  *** reconstructions: %s" % fname)
Beispiel #5
0
def rec(params):
    
    data_shape = file_io.get_dx_dims(params)
    # Read parameters from YAML file
    params = config.yaml_args(params, params.parameter_file, str(params.file_name))
    # Read parameters from DXchange file if requested
    params = file_io.auto_read_dxchange(params)
    if params.rotation_axis <= 0:
        params.rotation_axis =  data_shape[2]/2
        log.warning('  *** *** No rotation center given: assuming the middle of the projections at %f' % float(params.rotation_axis))
    
    # Select sinogram range to reconstruct
    if (params.reconstruction_type == "full"):
        if params.start_row:
            sino_start = params.start_row
        else:
            sino_start = 0
        if params.end_row < 0:
            sino_end = data_shape[1]
        else:
            sino_end = params.end_row 
        # If params.nsino_per_chunk < 1, use # of processor cores
        if params.nsino_per_chunk < 1:
            params.nsino_per_chunk = cpu_count()
        nSino_per_chunk = params.nsino_per_chunk * pow(2, int(params.binning))
        chunks = int(np.ceil((sino_end - sino_start)/nSino_per_chunk))
    elif (params.reconstruction_type == 'try'):
        _try_rec(params)
        return
    else: # "slice"        
        nSino_per_chunk = pow(2, int(params.binning))
        chunks = 1
        ssino = int(data_shape[1] * params.nsino)
        sino_start = ssino
        sino_end = sino_start + pow(2, int(params.binning)) 

    log.info("  *** reconstructing [%d] slices from slice [%d] to [%d] in [%d] chunks of [%d] slices each" % (
        (sino_end - sino_start) / pow(2, int(params.binning)),
        sino_start/pow(2, int(params.binning)),
        sino_end/pow(2, int(params.binning)),
        chunks, nSino_per_chunk/pow(2, int(params.binning))))
    
    strt = sino_start
    write_threads = []
    if chunks == 0:
        log.warning("  *** 0 chunks selected for reconstruction, "
                    "check your *start_row*, "
                    "*end_row*, and *nsino_per_chunk*.")
    for iChunk in range(0, chunks):
        log.info('chunk # %i/%i' % (iChunk + 1, chunks))
        sino = _compute_sino(iChunk, sino_start, sino_end, nSino_per_chunk, chunks, params) 

        # Read APS 32-BM raw data.
        proj, flat, dark, theta, rotation_axis = file_io.read_tomo(sino, params) 
        # What if sino overruns the size of data?
        if sino[1] - sino[0] > proj.shape[1]:
            log.warning("  *** Chunk size > remaining data size.")
            sino = [sino[0], sino[0] + proj.shape[1]]

        # Apply all preprocessing functions
        data = prep.all(proj, flat, dark, params, sino)
        del(proj, flat, dark)

        # unpad after phase retrieval
        if params.retrieve_phase_method == "paganin":
                params.phase_pad //= pow(2, int(params.binning))
                sino -= params.phase_pad                                
                data = data[:,-params.phase_pad[0]:data.shape[1]-params.phase_pad[1]]                
                log.info('  *** unpadding after phase retrieval gives slices [%i,%i] ' % (sino[0],sino[1]))
        
        # Reconstruct: this is for "slice" and "full" methods
        rotation_axis_rec = rotation_axis
        if (params.file_type == 'double_fov'):                                
            if(rotation_axis<data.shape[-1]//2):
                #if rotation center is on the left side of the ROI
                data = data[:,:,::-1]
                rotation_axis_rec = data.shape[-1]-rotation_axis                               
            # double FOV by adding zeros
            data = double_fov(data,rotation_axis_rec)    

        #Perform actual reconstruction
        rec = padded_rec(data, theta, rotation_axis_rec, params)

        # Save images
        recon_base_dir = reconstruction_folder(params)
        fpath = Path(params.file_name).resolve()
        if params.reconstruction_type == "full":
            recon_dir = recon_base_dir / "{}_rec".format(fpath.stem)
            if params.output_format == 'tiff_stack':
                fname = recon_dir / 'recon'
                log.debug("Full tiff dir: %s", fname)
                write_thread = threading.Thread(target=dxchange.write_tiff_stack,
                                                args = (rec,),
                                                kwargs = {'fname': str(fname),
                                                          'start': strt,
                                                          'overwrite': True})
            elif params.output_format == "hdf5":
                # HDF5 output
                fname = "{}.hdf".format(recon_dir)
                # file_io.write_hdf5(rec, fname=str(fname), dest_idx=slice(strt, strt+rec.shape[0]),
                #                    maxsize=(sino_end, *rec.shape[1:]), overwrite=(iChunk==0))
                ds_end = int(np.ceil(sino_end / pow(2, int(params.binning))))
                write_thread = threading.Thread(target=file_io.write_hdf5,
                                                args = (rec,),
                                                kwargs = {'fname': str(fname),
                                                          'dest_idx': slice(strt, strt+rec.shape[0]),
                                                          'maxsize': (ds_end, *rec.shape[1:]),
                                                          'overwrite': iChunk==0})
            else:
                log.error("  *** Unknown output_format '%s'", params.output_format)
                fname = "<Not saved (bad output-format)>"
                write_thread = None
            # Save the data to disk
            if write_thread is not None:
                write_thread.start()
                write_threads.append(write_thread)
            # Increment counter for which chunks to save
            strt += (sino[1] - sino[0])
        elif params.reconstruction_type == "slice":
            # Construct the path for where to save the tiffs
            fname = recon_base_dir / 'slice_rec' / 'recon_{}'.format(fpath.stem)
            dxchange.write_tiff(rec, fname=str(fname), overwrite=False)
        else:
            raise ValueError("Unknown value for *reconstruction type*: {}. "
                             "Valid options are {}"
                             "".format(params.reconstruction_type,
                                       config.SECTIONS['reconstruction']['reconstruction-type']['choices']))
        log.info("  *** reconstructions: %s" % fname)
    # Wait until the all threads are done writing data
    for thread in write_threads:
        thread.join()
Beispiel #6
0
def _try_rec(params):
    log.info("  *** *** starting 'try' reconstruction")
    data_shape = file_io.get_dx_dims(params)
    # Select sinogram range to reconstruct
    nSino_per_chunk = pow(2, int(params.binning))
    sino_start = int(data_shape[1] * params.nsino)
    sino_end = sino_start + pow(2, int(params.binning))
    if sino_end > data_shape[1]:
        log.warning('  *** *** *** binning would request row past end of data.  Truncating.')
        sino_start = data_shape[1] - pow(2, int(params.binning)) 
        sino_end = data_shape[1]

    log.info("reconstructing a slice binned from raw data rows [%d] to [%d]" % \
               (sino_start, sino_end))

    log.info('  *** binned rows [%i, %i]' % (sino_start/pow(2, int(params.binning)), sino_end/pow(2, int(params.binning))))
            
    sino = (int(sino_start), int(sino_end))
    # Set up the centers of rotation we will use
    # Read APS 32-BM raw data.
    proj, flat, dark, theta, rotation_axis = file_io.read_tomo(sino, params, True)
    
    # Apply all preprocessing functions
    data = prep.all(proj, flat, dark, params, sino)
    rec = []
    center_range = []
    # try passes an array of rotation centers and this is only supported by gridrec
    # reconstruction_algorithm_org = params.reconstruction_algorithm
    # params.reconstruction_algorithm = 'gridrec'
    if (params.file_type == 'standard' or params.file_type == 'double_fov'):
        center_search_width = params.center_search_width/np.power(2, float(params.binning))
        center_range = np.arange(rotation_axis-center_search_width, rotation_axis+center_search_width, 0.5)
        # stack = np.empty((len(center_range), data_shape[0], int(data_shape[2])))
        if (params.blocked_views):
            # blocked_views = params.blocked_views_end - params.blocked_views_start
            # stack = np.empty((len(center_range), data_shape[0]-blocked_views, int(data_shape[2])))
            st = params.blocked_views_start
            end = params.blocked_views_end
            #log.warning('%f %f',st,end)
            ids = np.where(((theta-st)%np.pi<0) + ((theta-st)%np.pi>end-st))[0]
            stack = np.empty((len(center_range), len(ids), int(data_shape[2])))
        else:
            stack = np.empty((len(center_range), data.shape[0], int(data.shape[2])))
        for i, axis in enumerate(center_range):
            stack[i] = data[:, 0, :]
        log.warning('  reconstruct slice [%d] with rotation axis range [%.2f - %.2f] in [%.2f] pixel steps' 
                        % (sino_start, center_range[0], center_range[-1], center_range[1] - center_range[0]))
        center_range_rec = center_range
        if (params.file_type == 'double_fov'):                                
            if(rotation_axis<stack.shape[-1]//2):
                #if rotation center is on the left side of the ROI
                stack = stack[:,:,::-1]
                center_range_rec = stack.shape[-1]-center_range
            # double FOV by adding zeros
            stack = double_fov_try(stack,center_range_rec)                
        if params.reconstruction_algorithm == 'gridrec':
            rec = padded_rec(stack, theta, center_range_rec, params)
        else:
            log.warning("  *** Doing try_center with '%s' instead of 'gridrec' is slow.", params.reconstruction_algorithm)
            rec = []
            for center in center_range_rec:
                rec.append(padded_rec(data[:, 0:1, :], theta, center, params))
            rec = np.asarray(rec)
    else:
        rotation_axis = params.rotation_axis_flip // pow(2,int(params.binning))
        center_search_width = params.center_search_width/np.power(2, float(params.binning))
        center_range = np.arange(rotation_axis-center_search_width, rotation_axis+center_search_width, 0.5)
        stitched_data = []
        rot_centers = np.zeros_like(center_range)
        #Loop through the assumed rotation centers
        for i, rot_center in enumerate(center_range): 
            params.rotation_axis_flip = rot_center
            stitched_data.append(file_io.flip_and_stitch(params, data, np.ones_like(data[0,...]),
                                                                np.zeros_like(data[0,...]))[0])
            rot_centers[i] = params.rotation_axis
        total_cols = np.min([i.shape[2] for i in stitched_data])
        theta180 = theta[:len(theta)//2] # take first half
        stack = np.empty((len(center_range), theta180.shape[0], total_cols))
        for i in range(center_range.shape[0]):
            stack[i] = stitched_data[i][:theta180.shape[0],0,:total_cols]
        del(stitched_data)
        rec = padded_rec(stack, theta180, rot_centers, params)
    # Save images to a temporary folder.
    fpath = Path(params.file_name).resolve()
    rec_dir = reconstruction_folder(params) / 'try_center' / fpath.stem
    for i,axis in enumerate(center_range):
        this_center = axis * np.power(2, float(params.binning))
        rfname = rec_dir / "recon_{:.2f}.tiff".format(this_center)
        dxchange.write_tiff(rec[i], fname=str(rfname), overwrite=True)