Пример #1
0
def ctvi_stats(ctvi, mask, histo):
    '''
    Doc todo
    '''

    ctvi = itk.imread(ctvi)
    mask = itk.imread(mask)

    check_same_geometry(ctvi, mask)

    data = itk.array_view_from_image(ctvi)
    mask = itk.array_view_from_image(mask)
    mask[mask != 0] = 1

    s = basics_stats(data, mask)

    print(
        f'Min/Max {s.min:.2f} {s.max:.2f}  Mean/Std {s.mean:.2f} {s.std:.2f}  '
        f' {s.pixels_count} pixels  Q10/Q90 {s.q10:.2f}  {s.q90:.2f} ')

    if histo == 0:
        exit(0)

    fig = plt.figure()
    m = mask.ravel()
    d = data.ravel()[m != 0]
    d = d[d != 0]  # there are  a lot of almost zeros values
    q1 = np.quantile(d, 0.9)
    plt.hist(d, bins=histo, range=(0, q1))
    plt.show()
Пример #2
0
def set_external_dose_zero(image, structure_file, structure):
    """Set all dose outside of patient's contour to zero 
    """

    img = None
    if type(image) == str:
        #Assume we have file path
        img = itk.imread(image)
    else:
        #Assume we have itk image object
        img = image

    ds = pydicom.dcmread(structure_file)

    aroi = roiutils.region_of_interest(ds, structure)
    mask = aroi.get_mask(img, corrected=False)

    pix_mask = itk.array_view_from_image(mask)
    pix_img = itk.array_view_from_image(img)

    if (pix_mask.shape != pix_img.shape):
        print("Inconsistent shapes of mask and image")

    pix_img_flat = pix_img.flatten()
    for i, val in enumerate(pix_mask.flatten()):
        if val == 0:
            pix_img_flat[i] = 0
    pix_img = pix_img_flat.reshape(pix_img.shape)
    img_modified = itk.image_view_from_array(pix_img)

    img_modified.CopyInformation(img)
    return img_modified
Пример #3
0
    def _get_array_data(self, img) -> np.ndarray:
        """
        Get the raw array data of the image, converted to Numpy array.

        Following PyTorch conventions, the returned array data has contiguous channels,
        e.g. for an RGB image, all red channel image pixels are contiguous in memory.
        The first axis of the returned array is the channel axis.

        Args:
            img: a ITK image object loaded from a image file.

        """
        channels = img.GetNumberOfComponentsPerPixel()
        if channels == 1:
            return itk.array_view_from_image(img, keep_axes=False)
        else:
            # The memory layout of itk.Image has all pixel's channels adjacent
            # in memory, i.e. R1G1B1R2G2B2R3G3B3. For PyTorch/MONAI, we need
            # channels to be contiguous, i.e. R1R2R3G1G2G3B1B2B3.
            arr = itk.array_view_from_image(img, keep_axes=False)
            dest = list(range(img.ndim))
            source = dest.copy()
            end = source.pop()
            source.insert(0, end)
            arr_contiguous_channels = np.moveaxis(arr, source, dest)
            return arr_contiguous_channels
Пример #4
0
def override_hu(img_file, structure_file, output_img, structure,
                hu):  #MAYBE JUST PASS THE IMAGE OBJECT AND DICOM OBJECT??
    """Override all HUs inside of specified structure"""

    img = itk.imread(img_file)
    ds = pydicom.dcmread(structure_file)

    # TESTING GATETOOLS
    aroi = roiutils.region_of_interest(ds, structure)
    mask = aroi.get_mask(img, corrected=False)
    ##aroi = rt.region_of_interest( ds, structure )
    ##mask = aroi.get_mask(img, corrected=False)

    pix_mask = itk.array_view_from_image(mask)
    pix_img = itk.array_view_from_image(img)
    if (pix_mask.shape != pix_img.shape):
        print("Inconsistent shapes of mask and image")

    pix_img_flat = pix_img.flatten()
    for i, val in enumerate(pix_mask.flatten()):
        if val == 1:
            pix_img_flat[i] = hu
    pix_img = pix_img_flat.reshape(pix_img.shape)
    img_modified = itk.image_view_from_array(pix_img)

    img_modified.CopyInformation(img)
    ##img_modified.SetSpacing( img.GetSpacing()  ) # "ElementSpacing" in .mhd
    ##img_modified.SetOrigin( img.GetOrigin() )    # "Offset" in .mhd

    itk.imwrite(img_modified, output_img)
Пример #5
0
 def test_image_projection(self):
     image = createImageExample()
     output = image_projection(image, 0, False)
     outputArray = itk.array_view_from_image(output)
     self.assertTrue(outputArray[13, 14] == 14 * 15)
     self.assertTrue(output.GetSpacing()[0] == 2)
     self.assertTrue(output.GetSpacing()[1] == 3.1)
     self.assertTrue(output.GetOrigin()[0] == 12.4)
     self.assertTrue(output.GetOrigin()[1] == -0.7)
     self.assertTrue(output.GetLargestPossibleRegion().GetSize()[0] == 23)
     self.assertTrue(output.GetLargestPossibleRegion().GetSize()[1] == 21)
     output = image_projection(image, 1, False)
     outputArray = itk.array_view_from_image(output)
     self.assertTrue(outputArray[8, 5] == 253)
     self.assertTrue(output.GetSpacing()[0] == 1.1)
     self.assertTrue(output.GetSpacing()[1] == 3.1)
     self.assertTrue(output.GetOrigin()[0] == 10)
     self.assertTrue(output.GetOrigin()[1] == -0.7)
     self.assertTrue(output.GetLargestPossibleRegion().GetSize()[0] == 15)
     self.assertTrue(output.GetLargestPossibleRegion().GetSize()[1] == 21)
     output = image_projection(image, 2)
     outputArray = itk.array_view_from_image(output)
     self.assertTrue(outputArray[6, 10] == 6 * 21)
     self.assertTrue(output.GetSpacing()[0] == 1.1)
     self.assertTrue(output.GetSpacing()[1] == 2)
     self.assertTrue(output.GetOrigin()[0] == 10)
     self.assertTrue(output.GetOrigin()[1] == 12.4)
     self.assertTrue(output.GetLargestPossibleRegion().GetSize()[0] == 15)
     self.assertTrue(output.GetLargestPossibleRegion().GetSize()[1] == 23)
     output = image_projection(image, 2, True)
     outputArray = itk.array_view_from_image(output)
     self.assertTrue(outputArray[6, 10] == 6)
Пример #6
0
def lung_mass_and_volume(img, img_mask):
    '''
    Mass in g
    Volume in L
    # HU = 1000 x (mu-mu_w) / (mu_w - mu_air)
    # mu = HU/1000 * (mu_w-mu_a) + mu_w
    # This is WRONG for H > 0 !
    # See for ex Schneider2000
    '''

    data = itk.array_view_from_image(img)
    mask = itk.array_view_from_image(img_mask)
    check_same_geometry(img, img_mask)

    # lung volume (be sure to consider all labels != 0 in the mask)
    pixel_vol = pix_vol(img)  # in mm3
    mask[mask != 0] = 1
    n = mask.sum()
    lung_vol = n * pixel_vol * 1e-6  # vol in L

    # lung mass
    mu_w = 1
    mu_a = 0.0
    d = data / 1000.0 * (mu_w - mu_a) + mu_w
    d[mask == 0] = 0.0
    lung_mass = d.sum() * pixel_vol * 1e-3  # mass in grams

    stat = Box()
    stat.mass_g = lung_mass
    stat.volume_L = lung_vol
    stat.pixels_count = n
    stat.pixel_volume_mm3 = pixel_vol
    return stat
Пример #7
0
    def GetSegmentationMask(self, region):
        seg = itk.array_view_from_image(self.segmentation)
        inmask = np.full(seg.shape, 1, dtype=np.int16)

        if not self.mask is None:
            inmask[itk.array_view_from_image(self.mask) == 0] = 0

        if region in self.segmentationRules.keys():
            rule = self.segmentationRules[region]

            # Limit to segmentation inclusion regions
            if not rule[0] is None:
                inmask = np.full(seg.shape, 0)
                for i in rule[0]:
                    inmask[seg == i] = 1

            # Eliminate exclusion regions
            if not rule[1] is None:
                for i in rule[1]:
                    inmask[seg == i] = 0

        else:
            inmask[seg != region] = 0

        # Apply global masking
        if not self.mask is None:
            inmask[itk.array_view_from_image(self.mask) == 0] = 0

        segMask = itk.image_from_array(inmask)
        segMask.SetSpacing(self.segmentation.GetSpacing())
        segMask.SetOrigin(self.segmentation.GetOrigin())
        segMask.SetDirection(self.segmentation.GetDirection())

        return (segMask)
Пример #8
0
 def __init__(self, cfg):
     self.out_dose_nxyz = cfg.out_dose_nxyz.astype(np.int)
     self.sim_dose_nxyz = cfg.sim_dose_nxyz.astype(np.int)
     if bool(cfg.mask_mhd):
         self.mask = itk.imread(os.path.join(cfg.workdir, cfg.mask_mhd))
         self.amask = itk.array_view_from_image(self.mask)
         if not (self.out_dose_nxyz[::-1] == self.amask.shape).all():
             msg = "mask resolution {} inconsistent with expected output dose resolution {}".format(
                 self.out_dose_nxyz[::-1], self.amask.shape)
             logger.error(msg)
             raise RuntimeError(msg)
     else:
         self.mask = None
     if bool(cfg.mass_mhd):
         #self.mass = itk.imread(cfg.mass_mhd)
         self.mass = itk.imread(os.path.join(cfg.workdir, cfg.mass_mhd))
         self.amass = itk.array_view_from_image(self.mass)
         if not (self.sim_dose_nxyz[::-1] == self.amass.shape).all():
             raise RuntimeError(
                 "mass resolution {} inconsistent with expected simulation dose resolution {}"
                 .format(self.sim_dose_nxyz[::-1], self.amass.shape))
     else:
         self.mass = None
     if bool(cfg.mass_mhd) != bool(cfg.mask_mhd):
         msg = "got mass_mhd={} and mask_mhd={}".format(
             cfg.mass_mhd, cfg.mask_mhd)
         msg += "you should provide EITHER both the mass and the mask file, OR neither of them."
         logger.error(msg)
         raise RuntimeError(msg)
     self.cfg = cfg
     syscfg = system_configuration.getInstance()
     self.ntop = syscfg["n top voxels for mean dose max"]
     self.toppct = syscfg[
         "dose threshold as fraction in percent of mean dose max"]
     self.reset()
Пример #9
0
def override_hu(image, structure_file, structure,
                hu):  #MAYBE JUST PASS THE IMAGE OBJECT AND DICOM OBJECT??
    """Override all HUs inside of specified structure"""

    ds = pydicom.dcmread(structure_file)
    img = None
    if type(image) == str:
        #Assume we have file path
        img = itk.imread(image)
    else:
        #Assume we have itk image object
        img = image

    aroi = roiutils.region_of_interest(ds, structure)
    mask = aroi.get_mask(img, corrected=False)

    pix_mask = itk.array_view_from_image(mask)
    pix_img = itk.array_view_from_image(img)
    if (pix_mask.shape != pix_img.shape):
        print("Inconsistent shapes of mask and image")

    pix_img_flat = pix_img.flatten()
    for i, val in enumerate(pix_mask.flatten()):
        if val == 1:
            pix_img_flat[i] = hu
    pix_img = pix_img_flat.reshape(pix_img.shape)
    img_modified = itk.image_view_from_array(pix_img)

    img_modified.CopyInformation(img)

    #itk.imwrite(img_modified, output_img )
    return img_modified
Пример #10
0
 def test_checkerboards(self):
     logger.debug(
         "test 3D checkerboards: have D=0.25 in even voxels and D=0.75 in odd voxels for ref image, vice versa for test image."
     )
     #for every voxel in the target image, the neighboring voxels in the ref image has the same dose
     #therefore the gamma index should be equal to spacing/dta for all voxels.
     #logger.debug('Test_GammaIndex3dIdenticalMesh test_checkerboards')
     nx, ny, nz = 4, 5, 6
     ix, iy, iz = np.meshgrid(np.arange(nx, dtype=int),
                              np.arange(ny, dtype=int),
                              np.arange(nz, dtype=int),
                              indexing='ij')
     a_odd = 0.5 * (((ix + iy + iz) % 2) == 1).astype(float) + 0.25
     a_even = 0.5 * (((ix + iy + iz) % 2) == 0).astype(float) + 0.25
     img_odd = itk.image_from_array(a_odd)
     img_even = itk.image_from_array(a_even)
     img_gamma_even_odd = gamma_index_3d_equal_geometry(img_even,
                                                        img_odd,
                                                        dd=10.,
                                                        dta=2.)
     img_gamma_odd_even = gamma_index_3d_equal_geometry(img_odd,
                                                        img_even,
                                                        dd=10.,
                                                        dta=2.)
     self.assertTrue(
         np.allclose(itk.array_view_from_image(img_gamma_odd_even),
                     itk.array_view_from_image(img_gamma_even_odd)))
     self.assertTrue(
         np.allclose(itk.array_view_from_image(img_gamma_odd_even), 0.5))
     logger.debug("DONE test checkerboards")
Пример #11
0
    def image_filter_wrapper(*args, **kwargs):
        have_array_input = False
        have_xarray_input = False

        args_list = list(args)
        for index, arg in enumerate(args):
            if _HAVE_XARRAY and isinstance(arg, xr.DataArray):
                have_xarray_input = True
                image = itk.image_from_xarray(arg)
                args_list[index] = image
            elif not isinstance(arg, itk.Object) and is_arraylike(arg):
                have_array_input = True
                array = np.asarray(arg)
                image = itk.image_view_from_array(array)
                args_list[index] = image

        potential_image_input_kwargs = ('input', 'input1', 'input2', 'input3')
        for key, value in kwargs.items():
            if (key.lower() in potential_image_input_kwargs
                    or "image" in key.lower()):
                if _HAVE_XARRAY and isinstance(value, xr.DataArray):
                    have_xarray_input = True
                    image = itk.image_from_xarray(value)
                    kwargs[key] = image
                elif not isinstance(value, itk.Object) and is_arraylike(value):
                    have_array_input = True
                    array = np.asarray(value)
                    image = itk.image_view_from_array(array)
                    kwargs[key] = image

        if have_xarray_input or have_array_input:
            # Convert output itk.Image's to numpy.ndarray's
            output = image_filter(*tuple(args_list), **kwargs)
            if isinstance(output, tuple):
                output_list = list(output)
                for index, value in output_list:
                    if isinstance(value, itk.Image):
                        if have_xarray_input:
                            data_array = itk.xarray_from_image(value)
                            output_list[index] = data_array
                        else:
                            array = itk.array_view_from_image(value)
                            output_list[index] = array
                return tuple(output_list)
            else:
                if isinstance(output, itk.Image):
                    if have_xarray_input:
                        output = itk.xarray_from_image(output)
                    else:
                        output = itk.array_view_from_image(output)
                return output
        else:
            return image_filter(*args, **kwargs)
Пример #12
0
 def test_EqualMesh(self):
     # For equal meshes, the "unequalmesh" implementation should give the
     # same results as "equal mesh" implementation.
     logger.debug('Test_GammaIndex3dUnequalMesh test_EqualMesh')
     np.random.seed(71234567)
     for i in range(5):
         logger.debug(
             "{}. comparing implementations with 'equal' and 'unequal' geometry assumptions"
             .format(i))
         nxyz = np.random.randint(25, 35, 3)
         oxyz = np.random.uniform(-100., 100., 3)
         sxyz = np.random.uniform(0.5, 2.5, 3)
         img_ref = itk.image_from_array(
             np.ones(nxyz, dtype=float).swapaxes(0, 2).copy())
         img_ref.SetOrigin(oxyz)
         img_ref.SetSpacing(sxyz)
         img_target = itk.image_from_array(
             np.random.normal(1., 0.05, nxyz).swapaxes(0, 2).copy())
         img_target.SetOrigin(oxyz)
         img_target.SetSpacing(sxyz)
         t0 = datetime.now()
         img_gamma_equal = gamma_index_3d_equal_geometry(img_ref,
                                                         img_target,
                                                         dd=3.,
                                                         dta=2.0)
         t1 = datetime.now()
         logger.debug(
             "{}. equal implementation with {} voxels took {}".format(
                 i, np.prod(nxyz), t1 - t0))
         img_gamma_unequal = gamma_index_3d_unequal_geometry(img_ref,
                                                             img_target,
                                                             dd=3.,
                                                             dta=2.0)
         t2 = datetime.now()
         logger.debug(
             "{}. unequal implementation with {} voxels took {}".format(
                 i, np.prod(nxyz), t2 - t1))
         aeq = itk.array_view_from_image(img_gamma_equal)
         auneq = itk.array_view_from_image(img_gamma_unequal)
         logger.debug("eq min/median/mean/max={}/{}/{}/{}".format(
             np.min(aeq), np.median(aeq), np.mean(aeq), np.max(aeq)))
         logger.debug("uneq min/median/mean/max={}/{}/{}/{}".format(
             np.min(auneq), np.median(auneq), np.mean(auneq),
             np.max(auneq)))
         logger.debug("{} out of {} are close".format(
             np.sum(np.isclose(aeq, auneq)), np.prod(aeq.shape)))
         logger.debug("eq first 2x2x2: {}".format(aeq[:2, :2, :2]))
         logger.debug("uneq first 2x2x2: {}".format(auneq[:2, :2, :2]))
         logger.debug("eq last 2x2x2: {}".format(aeq[-2:, -2:, -2:]))
         logger.debug("uneq last 2x2x2: {}".format(auneq[-2:, -2:, -2:]))
         self.assertTrue(np.allclose(aeq, auneq))
         logger.debug("Yay!")
Пример #13
0
def ctvi(exhale, inhale, lung_mask, output, radius_erode_mask, sigma_gauss,
         radius_median, rho_normalize):
    '''
    Doc todo
    '''

    exhale = itk.imread(exhale)
    inhale = itk.imread(inhale)
    lung_mask = itk.imread(lung_mask)

    # options
    options = Box()
    options.ventil_type = 'Kipritidis2015'
    options.rho_normalize = rho_normalize
    options.sigma_gauss = sigma_gauss
    options.radius_median = radius_median
    options.remove_10pc = False
    options.mass_corrected_inhale = True

    if radius_erode_mask != 0:
        mask = itk.array_view_from_image(lung_mask)
        mask[mask != 0] = 1
        lung_mask = erode_mask(lung_mask, radius_erode_mask)

    # go
    ctvi = compute_ctvi(exhale, inhale, lung_mask, options)

    itk.imwrite(ctvi, output)
Пример #14
0
def itkimage_to_json(itkimage, manager=None):
    """Serialize a Python itk.Image object.

    Attributes of this dictionary are to be passed to the JavaScript itkimage
    constructor.
    """
    if itkimage is None:
        return None
    else:
        direction = itkimage.GetDirection()
        directionMatrix = direction.GetVnlMatrix()
        directionList = []
        dimension = itkimage.GetImageDimension()
        pixelArr = itk.array_view_from_image(itkimage)
        compressor = zstd.ZstdCompressor(level=3)
        compressed = compressor.compress(pixelArr.data)
        pixelArrCompressed = memoryview(compressed)
        for col in range(dimension):
            for row in range(dimension):
                directionList.append(directionMatrix.get(row, col))
        componentType, pixelType = _image_to_type(itkimage)
        imageType = dict(dimension=dimension,
                         componentType=componentType,
                         pixelType=pixelType,
                         components=itkimage.GetNumberOfComponentsPerPixel())
        return dict(imageType=imageType,
                    origin=tuple(itkimage.GetOrigin()),
                    spacing=tuple(itkimage.GetSpacing()),
                    size=tuple(itkimage.GetBufferedRegion().GetSize()),
                    direction={
                        'data': directionList,
                        'rows': dimension,
                        'columns': dimension
                    },
                    compressedData=pixelArrCompressed)
Пример #15
0
 def test_Shift(self):
     # two images identical up to a translation less than half the spacing should yield a gamma index
     # equal to the ratio of the length of the translation vector and the DTA.
     logger.debug('Test_GammaIndex3dUnequalMesh test_Shift')
     np.random.seed(1234568)
     for i in range(5):
         logger.debug("shift image no. {}".format(i))
         nxyz = np.random.randint(5, 15, 3)
         oxyz = np.random.uniform(-100., 100., 3)
         sxyz = np.random.uniform(0.5, 2.5, 3)
         txyz = np.random.uniform(-0.5, 0.5, 3) * sxyz
         data = np.random.normal(1., 0.1, nxyz)
         img_ref = itk.image_from_array(data.swapaxes(0, 2).copy())
         img_ref.SetSpacing(sxyz)
         img_ref.SetOrigin(oxyz)
         img_target = itk.image_from_array(data.swapaxes(
             0, 2).copy())  # same as ref
         img_target.SetSpacing(sxyz)  # same as ref
         img_target.SetOrigin(oxyz + txyz)  # translated!
         ddp = 3.0  # %
         dta = 2.0  # mm
         img_gamma = gamma_index_3d_unequal_geometry(img_ref,
                                                     img_target,
                                                     dd=ddp,
                                                     dta=dta)
         agamma = itk.array_view_from_image(img_gamma).swapaxes(0, 2)
         gval_expected = np.sqrt(np.sum((txyz / dta)**2))
         self.assertTrue(np.allclose(agamma, gval_expected))
         logger.debug("ok #voxels={} gval_exp={}".format(
             np.prod(nxyz), gval_expected))
 def get_profile(image_or_array):
     image_from_array = to_itk_image(image_or_array)
     if image_from_array:
         image_ = image_from_array
     else:
         image_ = image_or_array
     image_array = itk.array_view_from_image(image_)
     dimension = image_.GetImageDimension()
     distance = np.sqrt(
         sum([(profiler.point1[ii] - profiler.point2[ii])**2
              for ii in range(dimension)]))
     index1 = tuple(
         image_.TransformPhysicalPointToIndex(
             tuple(profiler.point1[:dimension])))
     index2 = tuple(
         image_.TransformPhysicalPointToIndex(
             tuple(profiler.point2[:dimension])))
     num_points = int(
         np.round(
             np.sqrt(
                 sum([(index1[ii] - index2[ii])**2
                      for ii in range(dimension)])) * 2.1))
     coords = [
         np.linspace(index1[ii], index2[ii], num_points)
         for ii in range(dimension)
     ]
     mapped = scipy.ndimage.map_coordinates(image_array,
                                            np.vstack(coords[::-1]),
                                            order=order,
                                            mode='nearest')
     return np.linspace(0.0, distance, num_points), mapped
Пример #17
0
def get_stats_struct(uncertpath, dicom_struct, struct_name):
    """Generate stats from a dose image and uncertainty image;
    but only for pixels inside specified structure
    """
    uncertimg = itk.imread(uncertpath)
    uncert_flat = itk.array_from_image(uncertimg).flatten()
    ds = pydicom.dcmread(dicom_struct)

    aroi = roiutils.region_of_interest(ds, struct_name)
    mask = aroi.get_mask(uncertimg, corrected=False)
    mask_voxels_flat = itk.array_view_from_image(mask).flatten()

    relevant_uncerts = []
    for i, val in enumerate(mask_voxels_flat):
        if val == 1:
            relevant_uncerts.append(uncert_flat[i])

    relevant_uncerts = np.array(relevant_uncerts)

    print()
    print("Number of voxels in {} = {}".format(struct_name,
                                               len(relevant_uncerts)))
    print("Mean uncertainty = {}".format(relevant_uncerts.mean()))
    print("Median = {}".format(np.median(relevant_uncerts)))
    print("Max = {}".format(relevant_uncerts.max()))
    print("Min = {}".format(relevant_uncerts.min()))
    print("Std dev = {}".format(relevant_uncerts.std()))

    # Make histogram
    ymax = int(relevant_uncerts.max() * 100 + 2)
    binsize = 0.01
    bins = [i * binsize for i in range(int(ymax / binsize))]
    plt.hist(100 * relevant_uncerts, bins=bins)
    plt.xlabel("Dose uncertainty (%)")
    plt.show()
def test_image_from_image_layer_metadata():
    data = np.random.randint(256, size=(10, 10, 3), dtype=np.uint8)
    metadata = {"wookies": 7, "units": "mm"}
    image_layer = napari.layers.Image(data, metadata=metadata)
    image = itk_napari_conversion.image_from_image_layer(image_layer)
    assert np.array_equal(data, itk.array_view_from_image(image))
    assert image["wookies"] == 7
    assert image["units"] == "mm"
def test_image_from_image_layer_scale():
    data = np.random.randint(256, size=(10, 10), dtype=np.uint8)
    metadata = {"wookies": 7, "units": "mm"}
    scale = [1.1, 2.2]
    image_layer = napari.layers.Image(data, scale=scale)
    image = itk_napari_conversion.image_from_image_layer(image_layer)
    assert np.array_equal(data, itk.array_view_from_image(image))
    assert np.allclose(scale, np.array(image["spacing"]))
def test_image_from_image_layer_translate():
    data = np.random.randint(256, size=(10, 10), dtype=np.uint8)
    metadata = {"wookies": 7, "units": "mm"}
    translate = [1.1, 2.2]
    image_layer = napari.layers.Image(data, translate=translate)
    image = itk_napari_conversion.image_from_image_layer(image_layer)
    assert np.array_equal(data, itk.array_view_from_image(image))
    assert np.allclose(translate, np.array(image["origin"]))
Пример #21
0
 def estimate_uncertainty(self):
     if self.n < 2:
         return
     if self.mask:
         amask = itk.array_view_from_image(self.mask)
         logger.info(
             "applying mask with {} voxels enabled out of {}".format(
                 np.sum(amask > 0), np.prod(amask.shape)))
         self.dosesum *= amask
         self.dose2sum *= amask
     logger.info("dose sum is nonzero in {} voxels".format(
         np.sum(self.dosesum > 0)))
     logger.info("dose**2 sum is nonzero in {} voxels".format(
         np.sum(self.dose2sum > 0)))
     logger.info("sum of weights is {}, wmin={}, wmax={}".format(
         self.weightsum, self.wmin, self.wmax))
     amean = self.dosesum / self.weightsum
     amean2 = self.dose2sum / self.weightsum
     avariance = amean2 - amean**2
     m0 = avariance < 0
     logger.info("negative variance in {} voxels".format(np.sum(m0)))
     avariance[m0] = 0.
     m0 = amean < 0
     logger.info("negative mean in {} voxels".format(np.sum(m0)))
     amean[m0] = 0.
     m0 = amean > 0
     m00 = amean2 > 0
     logger.info("positive mean in {} voxels".format(np.sum(m0)))
     logger.info("positive mean of squares in {} voxels".format(
         np.sum(m00)))
     logger.info(
         "positive mean and mean of squares masks are different in {} voxels"
         .format(np.sum(m0 != m00)))
     logger.info("average/median of nonzero variance in is {}/{}".format(
         np.mean(avariance[m0]), np.median(avariance[m0])))
     logger.info("average/median of nonzero mean in is {}/{}".format(
         np.mean(amean[m0]), np.median(amean[m0])))
     logger.info(
         "average/median of nonzero mean of squares in is {}/{}".format(
             np.mean(amean2[m0]), np.median(amean2[m0])))
     logger.info(
         "average/median of nonzero square of the mean in is {}/{}".format(
             np.mean(amean[m0]**2), np.median(amean[m0]**2)))
     std_pct = np.full_like(avariance, 100.)
     std_pct[m0] = np.sqrt(avariance[m0] / self.n) * 100. / amean[m0]
     dmax = np.mean(np.partition(amean.flat, -self.ntop)[-self.ntop:])
     dthr = dmax * self.toppct / 100.0
     mask = (amean > dthr)
     logger.info(
         "{} voxels have more than {} percent of the 'max dose'".format(
             np.sum(mask), self.toppct))
     self.mean_unc_pct = np.mean(std_pct[mask])
     # if no goal is specified, this will never converge
     converged = self.mean_unc_pct < self.cfg.unc_goal_pct
     logger.info(
         "'mean uncertainty' = {0:.2f} pct, goal = {1} pct, => {2}".format(
             self.mean_unc_pct, self.cfg.unc_goal_pct,
             "CONVERGED" if converged else "CONTINUE"))
Пример #22
0
 def test_five_2D_images(self):
     logger.info('Test_Sum test_five_2D_images')
     nx,ny = 4,5
     hundred = 100
     thousand = 1000
     spacing = (42.,24.)
     origin = (4242.,2424.)
     # float images
     imglistF = [ itk.image_from_array(np.arange(nx*ny,dtype=np.float32).reshape(nx,ny).copy()),
                  itk.image_from_array(np.arange(nx*ny,dtype=np.float32)[::-1].reshape(nx,ny).copy()),
                  itk.image_from_array(np.arange(0,nx*ny*hundred,hundred,dtype=np.float32).reshape(nx,ny).copy()),
                  itk.image_from_array(np.arange(0,nx*ny*hundred,hundred,dtype=np.float32)[::-1].reshape(4,5).copy()),
                  itk.image_from_array(thousand*np.ones((nx,ny),dtype=np.float32)) ]
     for imgF in imglistF:
         imgF.SetSpacing( spacing )
         imgF.SetOrigin( origin )
     imgsumF = image_sum(input_list=imglistF)
     logger.debug("got image with spacing {}".format(imgsumF.GetSpacing()))
     index = imgsumF.GetLargestPossibleRegion().GetSize() -1
     logger.debug("get sum value {} while expecting {}".format(imgsumF.GetPixel(index),4.*5. -1.))
     self.assertTrue( np.allclose(itk.array_view_from_image(imgsumF),nx*ny-1.+(nx*ny-1.)*hundred +thousand) ) # floats: approximate equality
     self.assertTrue( itk.array_from_image(imgsumF).shape == (nx,ny))
     self.assertTrue( np.allclose(imgsumF.GetSpacing(),spacing))
     self.assertTrue( np.allclose(imgsumF.GetOrigin(),origin))
     # unsigned short int images ("US" in itk lingo)
     nx,ny = 40,50
     ten = 10
     thirteen = 13
     spacing = (32.,23.)
     origin = (3232.,2323.)
     imglistUS = [ itk.image_from_array(np.arange(nx*ny,dtype=np.uint16).reshape(nx,ny).copy()),
                   itk.image_from_array(np.arange(nx*ny,dtype=np.uint16)[::-1].reshape(nx,ny).copy()),
                   itk.image_from_array(np.arange(0,ten*nx*ny,ten,dtype=np.uint16).reshape(nx,ny).copy()),
                   itk.image_from_array(np.arange(0,ten*nx*ny,ten,dtype=np.uint16)[::-1].reshape(nx,ny).copy()),
                   itk.image_from_array(thirteen*np.ones((nx,ny),dtype=np.uint16)) ]
     for imgUS in imglistUS:
         imgUS.SetSpacing( spacing )
         imgUS.SetOrigin( origin )
     imgsumUS = image_sum(input_list=imglistUS)
     logger.debug("got image with spacing {}".format(imgsumUS.GetSpacing()))
     logger.debug("get sum value {} while expecting {}".format(imgsumUS.GetPixel(index),40*50-1+10*40*50-10+13))
     self.assertTrue( (itk.array_view_from_image(imgsumUS)==nx*ny-1+ten*nx*ny-ten+thirteen).all() ) # ints: exact equality
     self.assertTrue( itk.array_from_image(imgsumUS).shape == (nx,ny))
     self.assertTrue( np.allclose(imgsumUS.GetSpacing(),spacing))
     self.assertTrue( np.allclose(imgsumUS.GetOrigin(),origin))
Пример #23
0
 def _validate_label_image_weights(self, proposal):
     """Check the number of weights equals the number of labels."""
     value = proposal['value']
     value = np.array(value, dtype=np.float32)
     if self.rendered_label_image:
         labels = len(np.unique(itk.array_view_from_image(self.rendered_label_image)))
         if labels != len(value):
             raise TraitError('Number of labels, {0}, does not equal number of label weights, {1}'.format(labels, len(value)))
     return value
Пример #24
0
    def _get_array_data(self, img: Image) -> np.ndarray:
        """
        Get the raw array data of the image, converted to Numpy array.

        Args:
            img: a ITK image object loaded from a image file.

        """
        return itk.array_view_from_image(img, keep_axes=not self.c_order_axis_indexing)
Пример #25
0
def _apply_operation_to_image_list(op, input_list, output_file=None):
    img_list = _image_list(input_list)
    if len(img_list) == 1:
        return _image_output(img_list[0], output_file)
    np_list = [ itk.array_view_from_image(img) for img in img_list]
    np_result = reduce(op, np_list)
    img = itk.image_from_array(np_result)
    img.CopyInformation(img_list[0])
    return _image_output(img, output_file)
Пример #26
0
    def _get_array_data(self, img) -> np.ndarray:
        """
        Get the raw array data of the image, converted to Numpy array.

        Args:
            img: a ITK image object loaded from a image file.

        """
        return itk.array_view_from_image(img, keep_axes=False)
Пример #27
0
    def get_profile(self, image_or_array=None,
                    point1=None, point2=None, order=None):
        """Calculate the line profile.

        Calculate the pixel intensity values along the line that connects
        the given two points.

        The image can be 2D or 3D. If any/all of the parameters are None, default
        vales are assigned.

        Parameters
        ----------
        image_or_array : array_like, itk.Image, or vtk.vtkImageData
            The 2D or 3D image to visualize.

        point1 : list of float
            List elements represent the 2D/3D coordinate of the point1.

        point2 : list of float
            List elements represent the 2D/3D coordinate of the point2.

        order : int, optional
            Spline order for line profile interpolation. The order has to be in the
            range 0-5.

        """

        if not have_scipy:
            raise RuntimeError('The scipy package in necessary for the line_profiler widget.')
        if not have_itk:
            raise RuntimeError('The itk package in necessary for the line_profiler widget.')

        if image_or_array is None:
            image_or_array = self.image
        if point1 is None:
            point1 = self.point1
        if point2 is None:
            point2 = self.point2
        if order is None:
            order = self.order
        image = to_itk_image(image_or_array)
        image_array = itk.array_view_from_image(image)
        dimension = image.GetImageDimension()
        distance = np.sqrt(
            sum([(point1[ii] - point2[ii])**2 for ii in range(dimension)]))
        index1 = tuple(image.TransformPhysicalPointToIndex(
            tuple(point1[:dimension])))
        index2 = tuple(image.TransformPhysicalPointToIndex(
            tuple(point2[:dimension])))
        num_points = int(np.round(
            np.sqrt(sum([(index1[ii] - index2[ii])**2 for ii in range(dimension)])) * 2.1))
        coords = [np.linspace(index1[ii], index2[ii], num_points)
                  for ii in range(dimension)]
        mapped = scipy.ndimage.map_coordinates(image_array, np.vstack(coords[::-1]),
                                               order=order, mode='nearest')
        return np.linspace(0.0, distance, num_points), mapped
Пример #28
0
 def test_scaling(self):
     logger.debug("test scaling small")
     # two images identical up to a scaling factor 1.03 should give gamma(3%)<=1.0 in all voxels
     logger.debug('Test_GammaIndex3dIdenticalMesh test_scaling')
     np.random.seed(1234567)
     a_rnd = np.random.uniform(0., 10., (4, 5, 6))
     img1 = itk.image_from_array(a_rnd)
     img2 = itk.image_from_array(1.03 * a_rnd)
     img_gamma = gamma_index_3d_equal_geometry(img1, img2, dd=3., dta=2.0)
     self.assertTrue((itk.array_view_from_image(img_gamma) < 1.0001).all())
     logger.debug("DONE test scaling")
Пример #29
0
 def test_identity(self):
     # two identical images should give gamma=0.0 in all voxels
     logger.debug("test identity")
     logger.debug('Test_GammaIndex3dIdenticalMesh test_identity')
     np.random.seed(1234567)
     a_rnd = np.random.uniform(0., 10., (4, 5, 6))
     img1 = itk.image_from_array(a_rnd)
     img2 = itk.image_from_array(a_rnd)
     img_gamma = gamma_index_3d_equal_geometry(img1, img2, dd=3., dta=2.0)
     self.assertTrue((itk.array_view_from_image(img_gamma) == 0.).all())
     logger.debug("DONE test identity")
Пример #30
0
def image_std(input_list=[],output_file=None):
    """
    Computes element-wise standard deviation of a list of image with equal geometry.
    """
    img_list = _image_list(input_list)
    if len(img_list) == 1:
        return _image_output(img_list[0], output_file)
    np_list = [ itk.array_view_from_image(img) for img in img_list]
    np_result = np.std(np_list, axis=0)
    img = itk.image_from_array(np_result)
    img.CopyInformation(img_list[0])
    return _image_output(img, output_file)