コード例 #1
0
ファイル: test_removal.py プロジェクト: gbzan/algotom
 def test_remove_blob_1d(self):
     list_1d = 0.5 * np.ones(self.size)
     list_1d[self.idx1:self.idx2] = 1.0
     mask_1d = np.zeros_like(list_1d)
     mask_1d[self.idx1:self.idx2] = 1.0
     list_corr = remo.remove_blob_1d(list_1d, mask_1d)
     nmean = np.mean(list_corr[self.idx1:self.idx2])
     num = np.abs(nmean - 0.5)
     self.assertTrue(num < self.eps)
コード例 #2
0
def generate_full_sinogram_helical_scan(index,
                                        tomo_data,
                                        num_proj,
                                        pixel_size,
                                        y_start,
                                        y_stop,
                                        pitch,
                                        scan_type="180",
                                        angles=None,
                                        flat=None,
                                        dark=None,
                                        mask=None,
                                        crop=(0, 0, 0, 0)):
    """
    Generate a full sinogram from a helical scan dataset which is a hdf/nxs
    object (Ref. [1]_). Full sinogram is all 1D projection of the same slice of
    a sample staying inside the field of view.

    Parameters
    ----------
    index : int
        Index of the sinogram.
    tomo_data : hdf object.
        3D array.
    num_proj : int
        Number of projections per 180-degree.
    pixel_size : float
        Pixel size. The unit must be the same as y-position.
    y_start : float
        Y-position of the stage at the beginning of the scan.
    y_stop : float
        Y-position of the stage at the end of the scan.
    pitch : float
        The distance which the y-stage is translated in one full rotation.
    scan_type : {"180", "360"}
        Data acquired is the 180-degree type or 360-degree type [1].
    angles : array_like, optional
        1D array. List of angles (degree) corresponding to acquired projections.
    flat : array_like, optional
        Flat-field image used for flat-field correction.
    dark : array_like, optional
        Dark-field image used for flat-field correction.
    mask : array_like, optional
        Used for removing streak artifacts caused by blobs in the flat-field
        image.
    crop : tuple of int, optional
        Used for cropping images.

    Returns
    -------
    sinogram : array_like
        2D array. Full sinogram.
    list_angle : array_like
        1D array. List of angles corresponding to the generated sinogram.

    References
    ----------
    .. [1] https://doi.org/10.1364/OE.418448
    """
    (depth0, height0, width0) = tomo_data.shape
    (crop_top, crop_bottom, crop_left, crop_right) = crop
    top = crop_top
    bottom = height0 - crop_bottom
    left = crop_left
    right = width0 - crop_right
    width = right - left
    height = bottom - top
    if flat is None:
        flat = np.ones((height0, width0), dtype=np.float32)
    if dark is None:
        dark = np.zeros((height0, width0), dtype=np.float32)
    if angles is None:
        step_angle = 180.0 / (num_proj - 1)
        angles = np.arange(0, depth0) * step_angle
    flat_dark = flat - dark
    FoV = pixel_size * height
    y_step = pitch / (2.0 * (num_proj - 1))
    if scan_type == "180":
        y_e = y_stop - pitch / 2.0
        y_s = y_start + pitch / 2.0
    else:
        y_e = y_stop - pitch
        y_s = y_start + pitch
    num_proj_used = int(np.floor(FoV / y_step)) - 1
    y_pos = (index - 1) * pixel_size + y_s
    i0 = int(np.ceil((y_e - y_pos) / y_step))
    if (i0 < 0) or (i0 >= depth0):
        raise ValueError(
            "Sinogram index {0} requests a projection index {1} which "
            "is out of the projection range [0, {2}]".format(
                index, i0, depth0 - 1))
    if (i0 + num_proj_used) >= depth0:
        raise ValueError(
            "Sinogram index {0} requests projection-indices in the range of "
            "[{1}, {2}] which is out of the data range [0, {3}]".format(
                index, i0, i0 + num_proj_used, depth0 - 1))
    sinogram = np.zeros((num_proj_used, width), dtype=np.float32)
    for i in range(i0, i0 + num_proj_used):
        j0 = (y_e + FoV - i * y_step - y_pos) / pixel_size - 1
        if (j0 < 0) or (j0 >= height):
            raise ValueError(
                "Requested row index {0} of projection {1} is out of"
                " the range [0, {2}]".format(j0, i0, height))
        j0 = np.clip(j0, 0, height - 1)
        jd = int(np.floor(j0))
        ju = int(np.ceil(j0))
        list_down = (tomo_data[i, jd + crop_top, left:right] -
                     dark[jd + crop_top,
                          left:right]) / flat_dark[jd + crop_top, left:right]
        if mask is not None:
            list_down = remo.remove_blob_1d(list_down, mask[jd + crop_top,
                                                            left:right])
        if ju != jd:
            list_up = (tomo_data[i, ju + crop_top, left:right] -
                       dark[ju + crop_top,
                            left:right]) / flat_dark[ju + crop_top, left:right]
            if mask is not None:
                list_up = remo.remove_blob_1d(list_up, mask[ju + crop_top,
                                                            left:right])
            sinogram[i - i0] = list_down * (ju - j0) / (ju - jd) + list_up * (
                j0 - jd) / (ju - jd)
        else:
            sinogram[i - i0] = list_down
    list_angle = angles[i0:i0 + num_proj_used]
    return sinogram, list_angle
コード例 #3
0
def generate_sinogram_helical_scan(index,
                                   tomo_data,
                                   num_proj,
                                   pixel_size,
                                   y_start,
                                   y_stop,
                                   pitch,
                                   scan_type="180",
                                   angles=None,
                                   flat=None,
                                   dark=None,
                                   mask=None,
                                   crop=(0, 0, 0, 0)):
    """
    Generate a 180-degree sinogram or a 360-degree sinogram from a helical
    scan dataset which is a hdf/nxs object (Ref. [1]_).

    Parameters
    ----------
    index : int
        Index of the sinogram.
    tomo_data : hdf object.
        3D array.
    num_proj : int
        Number of projections per 180-degree.
    pixel_size : float
        Pixel size. The unit must be the same as y-position.
    y_start : float
        Y-position of the stage at the beginning of the scan.
    y_stop : float
        Y-position of the stage at the end of the scan.
    pitch : float
        The distance which the y-stage is translated in one full rotation.
    scan_type : {"180", "360"}
        One of two options: "180" for generating a 180-degree sinogram or
        "360" for generating a 360-degree sinogram.
    angles : array_like, optional
        1D array. List of angles (degree) corresponding to acquired projections.
    flat : array_like, optional
        Flat-field image used for flat-field correction.
    dark : array_like, optional
        Dark-field image used for flat-field correction.
    mask : array_like, optional
        Used for removing streak artifacts caused by blobs in the flat-field
        image.
    crop : tuple of int, optional
        Used for cropping images.

    Returns
    -------
    sinogram : array_like
        2D array. 180-degree sinogram or 360-degree sinogram.
    list_angle : array_like
        1D array. List of angles corresponding to the generated sinogram.

    References
    ----------
    .. [1] https://doi.org/10.1364/OE.418448
    """
    max_index = calc.calculate_maximum_index(y_start, y_stop, pitch,
                                             pixel_size, scan_type)
    (y_s, y_e) = calc.calculate_reconstructable_height(y_start, y_stop, pitch,
                                                       scan_type)
    if index < 0 or index > max_index:
        msg1 = "Requested index {0} is out of available index-range" \
               " [0, {1}]\n".format(index, max_index)
        msg2 = "corresponding to reconstructable heights" \
               " [{0}, {1}]".format(y_s, y_e)
        raise ValueError(msg1 + msg2)
    (depth0, height0, width0) = tomo_data.shape
    (crop_top, crop_bottom, crop_left, crop_right) = crop
    top = crop_top
    bottom = height0 - crop_bottom
    left = crop_left
    right = width0 - crop_right
    width = right - left
    height = bottom - top
    if flat is None:
        flat = np.ones((height0, width0), dtype=np.float32)
    if dark is None:
        dark = np.zeros((height0, width0), dtype=np.float32)
    if angles is None:
        step_angle = 180.0 / (num_proj - 1)
        angles = np.arange(0, depth0) * step_angle
    flat_dark = flat - dark
    FoV = pixel_size * height
    y_step = pitch / (2.0 * (num_proj - 1))
    if scan_type == "180":
        num_proj_used = num_proj
    else:
        num_proj_used = 2 * (num_proj - 1) + 1
    y_pos = (index - 1) * pixel_size + y_s
    i0 = int(np.ceil((y_e - y_pos) / y_step))
    if (i0 < 0) or (i0 >= depth0):
        raise ValueError("Sinogram index {0} requests a projection index {1}"
                         " which is out of the data range [0, {2}]".format(
                             index, i0, depth0 - 1))
    sinogram = np.zeros((num_proj_used, width), dtype=np.float32)
    for i in range(i0, i0 + num_proj_used):
        j0 = (y_e + FoV - i * y_step - y_pos) / pixel_size - 1
        if (j0 < 0) or (j0 >= height):
            raise ValueError(
                "Requested row index {0} of projection {1} is out of the"
                " range [0, {2}]".format(j0, i0, height - 1))
        j0 = np.clip(j0, 0, height - 1)
        jd = int(np.floor(j0))
        ju = int(np.ceil(j0))
        list_down = (tomo_data[i, jd + crop_top, left:right] -
                     dark[jd + crop_top,
                          left:right]) / flat_dark[jd + crop_top, left:right]
        if mask is not None:
            list_down = remo.remove_blob_1d(list_down, mask[jd + crop_top,
                                                            left:right])
        if ju != jd:
            list_up = (tomo_data[i, ju + crop_top, left: right]
                       - dark[ju + crop_top, left: right]) \
                      / flat_dark[ju + crop_top, left: right]
            if mask is not None:
                list_up = remo.remove_blob_1d(list_up, mask[ju + crop_top,
                                                            left:right])
            sinogram[i - i0] = list_down * (ju - j0) / (ju - jd) + list_up * (
                j0 - jd) / (ju - jd)
        else:
            sinogram[i - i0] = list_down
    list_angle = angles[i0:i0 + num_proj_used]
    return sinogram, list_angle