Ejemplo n.º 1
0
def test_more_change_orientation(fake_3dimage_sct, fake_3dimage_sct_vis):
    path_tmp = tmp_create(basename="test_reorient")
    path_tmp = "."

    im_src = fake_3dimage_sct.copy()
    im_src.save(os.path.join(path_tmp, "src.nii"), mutable=True)

    print(im_src.orientation, im_src.data.shape)

    def orient2shape(orient):
        # test-data-specific thing
        letter2dim = dict(
            L=7,
            R=7,
            A=8,
            P=8,
            I=9,
            S=9,
        )
        return tuple([letter2dim[x] for x in orient])

    orientation = im_src.orientation  # LPI
    assert im_src.header.get_best_affine()[:3, 3].tolist() == [0, 0, 0]
    im_dst = msct_image.change_orientation(im_src, "RPI")
    print(im_dst.orientation, im_dst.data.shape)
    assert im_dst.data.shape == orient2shape("RPI")
    assert im_dst.header.get_best_affine()[:3, 3].tolist() == [7 - 1, 0, 0]

    # spot check
    orientation = im_src.orientation  # LPI
    im_dst = msct_image.change_orientation(im_src, "IRP")
    print(im_dst.orientation, im_dst.data.shape)
    assert im_dst.data.shape == orient2shape("IRP")

    # to & fro
    im_dst2 = msct_image.change_orientation(im_dst, orientation)
    print(im_dst2.orientation, im_dst2.data.shape)
    assert im_dst2.orientation == im_src.orientation
    assert im_dst2.data.shape == orient2shape(orientation)
    assert (im_dst2.data == im_src.data).all()
    assert np.allclose(im_src.header.get_best_affine(),
                       im_dst2.header.get_best_affine())

    #fn = os.path.join(path_tmp, "pouet.nii")
    im_ref = fake_3dimage_sct.copy()
    im_src = fake_3dimage_sct.copy()
    orientation = im_src.orientation
    im_src.change_orientation("ASR").change_orientation(orientation)
    assert im_src.orientation == im_ref.orientation
    assert (im_dst2.data == im_src.data).all()
    assert np.allclose(im_src.header.get_best_affine(),
                       im_ref.header.get_best_affine())

    im_dst2 = msct_image.change_orientation(im_dst, orientation)
    print(im_dst2.orientation, im_dst2.data.shape)
    assert im_dst2.orientation == im_src.orientation
    assert im_dst2.data.shape == orient2shape(orientation)
    assert (im_dst2.data == im_src.data).all()
    assert np.allclose(im_src.header.get_best_affine(),
                       im_dst2.header.get_best_affine())

    # copy
    im_dst = im_src.copy().change_orientation("IRP")
    assert im_dst.data.shape == orient2shape("IRP")
    print(im_dst.orientation, im_dst.data.shape)

    print("Testing orientation persistence")
    img = im_src.copy()
    orientation = img.orientation
    fn = os.path.join(path_tmp, "pouet.nii")
    img.change_orientation("PIR").save(fn)
    assert img.data.shape == orient2shape("PIR")
    img = msct_image.Image(fn)
    assert img.orientation == "PIR"
    assert img.data.shape == orient2shape("PIR")
    print(img.orientation, img.data.shape)

    # typical pattern
    img = fake_3dimage_sct_vis.copy()
    print(img.header.get_best_affine())
    orientation = img.orientation
    path_tmp = "."
    fn = os.path.join(path_tmp, "vis.nii")
    fn2 = img.save(fn, mutable=True).change_orientation(
        "ALS", generate_path=True).save().absolutepath
    img = msct_image.Image(fn2)
    assert img.orientation == "ALS"
    assert img.data.shape == orient2shape("ALS")
    print(img.header.get_best_affine())

    fn2 = img.save(fn, mutable=True).change_orientation(
        "RAS", generate_path=True).save().absolutepath
    img = msct_image.Image(fn2)
    assert img.orientation == "RAS"
    assert img.data.shape == orient2shape("RAS")
    print(img.header.get_best_affine())

    fn2 = img.save(fn, mutable=True).change_orientation(
        "RPI", generate_path=True).save().absolutepath
    img = msct_image.Image(fn2)
    assert img.orientation == "RPI"
    assert img.data.shape == orient2shape("RPI")
    print(img.header.get_best_affine())

    fn2 = img.save(fn, mutable=True).change_orientation(
        "PLI", generate_path=True).save().absolutepath
    img = msct_image.Image(fn2)
    assert img.orientation == "PLI"
    assert img.data.shape == orient2shape("PLI")
    print(img.header.get_best_affine())

    # print(src.header)
    possibilities = [
        "ASR",
        "SRA",
        "RAS",
    ]
    possibilities = msct_image.all_refspace_strings()
    for orientation in possibilities:
        dst = msct_image.change_orientation(im_src, orientation)
        # dst.save("pouet-{}.nii".format(dst.orientation))
        print(orientation, dst.orientation, dst.data.shape, dst.dim)
        assert orientation == dst.orientation
Ejemplo n.º 2
0
def test_change_orientation(fake_3dimage_sct, fake_3dimage_sct_vis):

    path_tmp = tmp_create(basename="test_reorient")
    path_tmp = "."

    print("Spot-checking that physical coordinates don't change")
    for shape_is in (1, 2, 3):
        shape = (1, 1, shape_is)
        print("Simple image with shape {}".format(shape))

        data = np.ones(shape, order="F")
        data[:, :, shape_is - 1] += 1
        im_src = fake_3dimage_sct_custom(data)
        im_dst = msct_image.change_orientation(im_src, "ASR")
        # Basic check
        assert im_dst.orientation == "ASR"
        # Basic data check
        assert im_dst.data.mean() == im_src.data.mean()
        # Basic header check: check that the same voxel
        # remains at the same physical position
        aff_src = im_src.header.get_best_affine()
        aff_dst = im_dst.header.get_best_affine()

        # Take the extremities "a" & "z"...
        # consider the original LPI position
        pta_src = np.array([[0, 0, 0, 1]]).T
        ptz_src = np.array([[0, 0, shape_is - 1, 1]]).T
        # and the position in ASR
        pta_dst = np.array([[0, shape_is - 1, 0, 1]]).T
        ptz_dst = np.array([[0, 0, 0, 1]]).T
        # The physical positions should be:
        posa_src = np.matmul(aff_src, pta_src)
        posa_dst = np.matmul(aff_dst, pta_dst)
        print("A at src {}".format(posa_src.T))
        print("A at dst {}".format(posa_dst.T))
        posz_src = np.matmul(aff_src, ptz_src)
        posz_dst = np.matmul(aff_dst, ptz_dst)
        # and they should be equal
        assert (posa_src == posa_dst).all()
        assert (posz_src == posz_dst).all()
        fn = "".join(str(x) for x in im_src.data.shape)
        im_src.save("{}-src.nii".format(fn))
        im_dst.save("{}-dst.nii".format(fn))

    np.random.seed(0)

    print("More checking that physical coordinates don't change")
    if 1:
        shape = (7, 8, 9)
        print("Simple image with shape {}".format(shape))

        data = np.ones(shape, order="F") * 10
        data[4, 4, 4] = 4
        data[3, 3, 3] = 3
        data[0, 0, 0] = 0
        values = (0, 3, 4)

        im_ref = fake_3dimage_sct_custom(data)
        im_ref.header.set_xyzt_units("mm", "msec")

        import scipy.linalg

        def rand_rot():
            q, _ = scipy.linalg.qr(np.random.randn(3, 3))
            if scipy.linalg.det(q) < 0:
                q[:, 0] = -q[:, 0]
            return q

        affine = im_ref.header.get_best_affine()
        affine[:3, :3] = rand_rot()
        affine[3, :3] = 0.0
        affine[:3, 3] = np.random.random((3))
        affine[3, 3] = 1.0

        affine[0, 0] *= 2
        im_ref.header.set_sform(affine, code='scanner')

        orientations = msct_image.all_refspace_strings()
        for ori_src in orientations:
            for ori_dst in orientations:
                print("{} -> {}".format(ori_src, ori_dst))
                im_src = msct_image.change_orientation(im_ref, ori_src)
                im_dst = msct_image.change_orientation(im_src, ori_dst)

                assert im_src.orientation == ori_src
                assert im_dst.orientation == ori_dst
                assert im_dst.data.mean() == im_src.data.mean()

                # Basic header check: check that the same voxel
                # remains at the same physical position
                aff_src = im_src.header.get_best_affine()
                aff_dst = im_dst.header.get_best_affine()

                data_src = np.array(im_src.data)
                data_dst = np.array(im_dst.data)

                for value in values:
                    pt_src = np.argwhere(data_src == value)[0]
                    pt_dst = np.argwhere(data_dst == value)[0]

                    pos_src = np.matmul(
                        aff_src,
                        np.hstack((pt_src, [1])).reshape((4, 1)))
                    pos_dst = np.matmul(
                        aff_dst,
                        np.hstack((pt_dst, [1])).reshape((4, 1)))
                    if 0:
                        print("P at src {}".format(pos_src.T))
                        print("P at dst {}".format(pos_dst.T))
                    assert np.allclose(pos_src, pos_dst, atol=1e-3)
Ejemplo n.º 3
0
def notest_transfo_more_exhaustive_wrt_orientations():

    dir_tmp = "."

    print("Figuring out which orientations work without workaround")

    all_orientations = msct_image.all_refspace_strings()

    orientations_ok = []
    orientations_ng = []
    orientations_dk = []

    for orientation_src in all_orientations:
        for orientation_ref in all_orientations:
            shift = np.array([1,2,3])
            shift_wanted = shift.copy()
            shift[2] *= -1 # ANTs / ITK reference frame is LPS, ours is LPI
            # (see docs or test_transfo_figure_out_ants_frame_exhaustive())

            print(" Shifting {} in {} ref {}".format(shift_wanted, orientation_src, orientation_ref))

            path_src = "warp2-{}.nii".format(orientation_src)
            img_src = fake_3dimage_sct().change_orientation(orientation_src).save(path_src)

            path_ref = "warp2-{}.nii".format(orientation_ref)
            img_ref = fake_3dimage_sct().change_orientation(orientation_ref).save(path_ref)


            # Create warping field
            shape = tuple(list(img_src.data.shape) + [1,3])
            data = np.zeros(shape, order="F")
            data[:,:,:,0] = shift

            path_warp = "warp-{}-{}-field.nii".format(orientation_src, orientation_ref)
            img_warp = fake_image_sct_custom(data)
            img_warp.header.set_intent('vector', (), '')
            img_warp.change_orientation(orientation_ref).save(path_warp)
            #print(" Affine:\n{}".format(img_warp.header.get_best_affine()))

            path_dst = "warp-{}-{}-dst.nii".format(orientation_src, orientation_ref)
            xform = sct_apply_transfo.Transform(path_src, path_warp, path_ref, path_dst)
            xform.apply()

            img_src2 = msct_image.Image(path_src)
            img_dst = msct_image.Image(path_dst)

            assert img_ref.orientation == img_dst.orientation
            assert img_ref.data.shape == img_dst.data.shape

            dat_src = img_src.data
            dat_dst = np.array(img_dst.data)

            value = 50505
            aff_src = img_src.header.get_best_affine()
            aff_dst = img_dst.header.get_best_affine()

            pt_src = np.argwhere(dat_src == value)[0]
            try:
                pt_dst = np.argwhere(dat_dst == value)[0]
                1/0
            except:
                # Work around numerical inaccuracy, that is somehow introduced by ANTs
                min_ = np.round(np.min(np.abs(dat_dst - value)), 1)
                pt_dst = np.array(np.unravel_index(np.argmin(np.abs(dat_dst - value)), dat_dst.shape))#, order="F"))

            print(" Point %s -> %s (%s) %s" % (pt_src, pt_dst, dat_dst[tuple(pt_dst)], min_))
            if min_ != 0:
                orientations_dk.append((orientation_src, orientation_ref))
                continue

            pos_src = np.matmul(aff_src, np.hstack((pt_src, [1])).reshape((4,1)))
            pos_dst = np.matmul(aff_dst, np.hstack((pt_dst, [1])).reshape((4,1)))

            displacement = (pos_dst - pos_src).reshape((-1))[:3]
            displacement_log = pt_dst - pt_src
            #print(" Displacement (logical): %s" % (displacement_log))
            if not np.allclose(displacement, shift_wanted):
                orientations_ng.append((orientation_src, orientation_ref))
                print(" \x1B[31;1mDisplacement (physical): %s\x1B[0m" % (displacement))
            else:
                orientations_ok.append((orientation_src, orientation_ref))
                print(" Displacement (physical): %s" % (displacement))
            print("")

    def ori_str(x):
        return " ".join(["{}->{}".format(x,y) for (x,y) in x])

    print("Orientations OK: {}".format(ori_str(orientations_ok)))
    print("Orientations NG: {}".format(ori_str(orientations_ng)))
    print("Orientations DK: {}".format(ori_str(orientations_dk)))
Ejemplo n.º 4
0
def test_transfo_figure_out_ants_frame_exhaustive():

    dir_tmp = "."
    all_orientations = msct_image.all_refspace_strings()
    #all_orientations = ("LPS", "LPI")

    print("Wondering which orientation is native to ANTs")

    working_orientations = [] # there can't be only one...

    for orientation in all_orientations:
        print(" Shifting +1,+1,+1 (in {})".format(orientation))

        path_src = "warp-{}-src.nii".format(orientation)
        img_src = fake_3dimage_sct().change_orientation(orientation).save(path_src)

        # Create warping field
        shape = tuple(list(img_src.data.shape) + [1,3])
        data = np.ones(shape, order="F")
        path_warp = "warp-{}-field.nii".format(orientation)
        img_warp = fake_image_sct_custom(data)
        img_warp.header.set_intent('vector', (), '')
        img_warp.change_orientation(orientation).save(path_warp)
        print(" Affine:\n{}".format(img_warp.header.get_best_affine()))

        path_dst = "warp-{}-dst.nii".format(orientation)
        xform = sct_apply_transfo.Transform(path_src, path_warp, path_src, path_dst)
        xform.apply()

        img_src2 = msct_image.Image(path_src)
        img_dst = msct_image.Image(path_dst)

        assert img_src.orientation == img_dst.orientation
        assert img_src.data.shape == img_dst.data.shape

        dat_src = img_src.data
        dat_dst = np.array(img_dst.data)

        value = 222
        aff_src = img_dst.header.get_best_affine()
        aff_dst = img_dst.header.get_best_affine()
        pt_src = np.array(np.unravel_index(np.argmin(np.abs(dat_src - value)), dat_src.shape))#, order="F"))
        pt_dst = np.array(np.unravel_index(np.argmin(np.abs(dat_dst - value)), dat_dst.shape))#, order="F"))
        print("Point %s -> %s" % (pt_src, pt_dst))

        pos_src = np.matmul(aff_src, np.hstack((pt_src, [1])).reshape((4,1)))
        pos_dst = np.matmul(aff_dst, np.hstack((pt_dst, [1])).reshape((4,1)))

        displacement = (pos_dst - pos_src).T[:3]
        print("Displacement (physical): %s" % (displacement))
        displacement = pt_dst - pt_src
        print("Displacement (logical): %s" % (displacement))

        assert dat_src.shape == dat_dst.shape

        if 0:
            for idx_slice in range(9):
                print(dat_src[...,idx_slice])
                print(dat_dst[...,idx_slice])
                print("")

        try:
            # Check same as before
            assert np.allclose(dat_dst[0,:,:], 0)
            assert np.allclose(dat_dst[:,0,:], 0)
            assert np.allclose(dat_dst[:,:,0], 0)
            assert np.allclose(dat_src[:-1,:-1,:-1], dat_dst[1:,1:,1:])
            working_orientations.append(orientation)
        except AssertionError as e:
            continue
            print("\x1B[31;1m Failed in {}\x1B[0m".format(orientation))
            for idx_slice in range(shape[2]):
                print(dat_src[...,idx_slice])
                print(dat_dst[...,idx_slice])
                print("")

    print("-> Working orientation: {}".format(" ".join(working_orientations)))
Ejemplo n.º 5
0
def test_more_change_orientation(fake_3dimage_sct, fake_3dimage_sct_vis):
    path_tmp = sct.tmp_create(basename="test_reorient")
    path_tmp = "."

    im_src = fake_3dimage_sct.copy()
    im_src.save(os.path.join(path_tmp, "src.nii"), mutable=True)

    print(im_src.orientation, im_src.data.shape)

    def orient2shape(orient):
        # test-data-specific thing
        letter2dim = dict(
         L=7,
         R=7,
         A=8,
         P=8,
         I=9,
         S=9,
        )
        return tuple([letter2dim[x] for x in orient])

    orientation = im_src.orientation # LPI
    assert im_src.header.get_best_affine()[:3,3].tolist() == [0,0,0]
    im_dst = msct_image.change_orientation(im_src, "RPI")
    print(im_dst.orientation, im_dst.data.shape)
    assert im_dst.data.shape == orient2shape("RPI")
    assert im_dst.header.get_best_affine()[:3,3].tolist() == [7-1,0,0]

    # spot check
    orientation = im_src.orientation # LPI
    im_dst = msct_image.change_orientation(im_src, "IRP")
    print(im_dst.orientation, im_dst.data.shape)
    assert im_dst.data.shape == orient2shape("IRP")

    # to & fro
    im_dst2 = msct_image.change_orientation(im_dst, orientation)
    print(im_dst2.orientation, im_dst2.data.shape)
    assert im_dst2.orientation == im_src.orientation
    assert im_dst2.data.shape == orient2shape(orientation)
    assert (im_dst2.data == im_src.data).all()
    assert np.allclose(im_src.header.get_best_affine(), im_dst2.header.get_best_affine())


    #fn = os.path.join(path_tmp, "pouet.nii")
    im_ref = fake_3dimage_sct.copy()
    im_src = fake_3dimage_sct.copy()
    orientation = im_src.orientation
    im_src.change_orientation("ASR").change_orientation(orientation)
    assert im_src.orientation == im_ref.orientation
    assert (im_dst2.data == im_src.data).all()
    assert np.allclose(im_src.header.get_best_affine(), im_ref.header.get_best_affine())


    im_dst2 = msct_image.change_orientation(im_dst, orientation)
    print(im_dst2.orientation, im_dst2.data.shape)
    assert im_dst2.orientation == im_src.orientation
    assert im_dst2.data.shape == orient2shape(orientation)
    assert (im_dst2.data == im_src.data).all()
    assert np.allclose(im_src.header.get_best_affine(), im_dst2.header.get_best_affine())



    # copy
    im_dst = im_src.copy().change_orientation("IRP")
    assert im_dst.data.shape == orient2shape("IRP")
    print(im_dst.orientation, im_dst.data.shape)


    print("Testing orientation persistence")
    img = im_src.copy()
    orientation = img.orientation
    fn = os.path.join(path_tmp, "pouet.nii")
    img.change_orientation("PIR").save(fn)
    assert img.data.shape == orient2shape("PIR")
    img = msct_image.Image(fn)
    assert img.orientation == "PIR"
    assert img.data.shape == orient2shape("PIR")
    print(img.orientation, img.data.shape)

    # typical pattern
    img = fake_3dimage_sct_vis.copy()
    print(img.header.get_best_affine())
    orientation = img.orientation
    path_tmp = "."
    fn = os.path.join(path_tmp, "vis.nii")
    fn2 = img.save(fn, mutable=True).change_orientation("ALS", generate_path=True).save().absolutepath
    img = msct_image.Image(fn2)
    assert img.orientation == "ALS"
    assert img.data.shape == orient2shape("ALS")
    print(img.header.get_best_affine())

    fn2 = img.save(fn, mutable=True).change_orientation("RAS", generate_path=True).save().absolutepath
    img = msct_image.Image(fn2)
    assert img.orientation == "RAS"
    assert img.data.shape == orient2shape("RAS")
    print(img.header.get_best_affine())


    fn2 = img.save(fn, mutable=True).change_orientation("RPI", generate_path=True).save().absolutepath
    img = msct_image.Image(fn2)
    assert img.orientation == "RPI"
    assert img.data.shape == orient2shape("RPI")
    print(img.header.get_best_affine())

    fn2 = img.save(fn, mutable=True).change_orientation("PLI", generate_path=True).save().absolutepath
    img = msct_image.Image(fn2)
    assert img.orientation == "PLI"
    assert img.data.shape == orient2shape("PLI")
    print(img.header.get_best_affine())

    #print(src.header)
    possibilities = [ "ASR", "SRA", "RAS", ]
    possibilities = msct_image.all_refspace_strings()
    for orientation in possibilities:
        dst = msct_image.change_orientation(im_src, orientation)
        #dst.save("pouet-{}.nii".format(dst.orientation))
        print(orientation, dst.orientation, dst.data.shape, dst.dim)
        assert orientation == dst.orientation
Ejemplo n.º 6
0
def test_change_orientation(fake_3dimage_sct, fake_3dimage_sct_vis):

    path_tmp = sct.tmp_create(basename="test_reorient")
    path_tmp = "."

    print("Spot-checking that physical coordinates don't change")
    for shape_is in (1,2,3):
        shape = (1,1,shape_is)
        print("Simple image with shape {}".format(shape))

        data = np.ones(shape, order="F")
        data[:,:,shape_is-1] += 1
        im_src = fake_3dimage_sct_custom(data)
        im_dst = msct_image.change_orientation(im_src, "ASR")
        # Basic check
        assert im_dst.orientation == "ASR"
        # Basic data check
        assert im_dst.data.mean() == im_src.data.mean()
        # Basic header check: check that the same voxel
        # remains at the same physical position
        aff_src = im_src.header.get_best_affine()
        aff_dst = im_dst.header.get_best_affine()

        # Take the extremities "a" & "z"...
        # consider the original LPI position
        pta_src = np.array([[0,0,0,1]]).T
        ptz_src = np.array([[0,0,shape_is-1,1]]).T
        # and the position in ASR
        pta_dst = np.array([[0,shape_is-1,0,1]]).T
        ptz_dst = np.array([[0,0,0,1]]).T
        # The physical positions should be:
        posa_src = np.matmul(aff_src, pta_src)
        posa_dst = np.matmul(aff_dst, pta_dst)
        print("A at src {}".format(posa_src.T))
        print("A at dst {}".format(posa_dst.T))
        posz_src = np.matmul(aff_src, ptz_src)
        posz_dst = np.matmul(aff_dst, ptz_dst)
        # and they should be equal
        assert (posa_src == posa_dst).all()
        assert (posz_src == posz_dst).all()
        fn = "".join(str(x) for x in im_src.data.shape)
        im_src.save("{}-src.nii".format(fn))
        im_dst.save("{}-dst.nii".format(fn))


    np.random.seed(0)

    print("More checking that physical coordinates don't change")
    if 1:
        shape = (7,8,9)
        print("Simple image with shape {}".format(shape))

        data = np.ones(shape, order="F") * 10
        data[4,4,4] = 4
        data[3,3,3] = 3
        data[0,0,0] = 0
        values = (0,3,4)

        im_ref = fake_3dimage_sct_custom(data)
        im_ref.header.set_xyzt_units("mm", "msec")

        import scipy.linalg

        def rand_rot():
            q, _ = scipy.linalg.qr(np.random.randn(3, 3))
            if scipy.linalg.det(q) < 0:
                q[:, 0] = -q[:, 0]
            return q

        affine = im_ref.header.get_best_affine()
        affine[:3,:3] = rand_rot()
        affine[3,:3] = 0.0
        affine[:3,3] = np.random.random((3))
        affine[3,3] = 1.0

        affine[0,0] *= 2
        im_ref.header.set_sform(affine, code='scanner')

        orientations = msct_image.all_refspace_strings()
        for ori_src in orientations:
            for ori_dst in orientations:
                print("{} -> {}".format(ori_src, ori_dst))
                im_src = msct_image.change_orientation(im_ref, ori_src)
                im_dst = msct_image.change_orientation(im_src, ori_dst)

                assert im_src.orientation == ori_src
                assert im_dst.orientation == ori_dst
                assert im_dst.data.mean() == im_src.data.mean()

                # Basic header check: check that the same voxel
                # remains at the same physical position
                aff_src = im_src.header.get_best_affine()
                aff_dst = im_dst.header.get_best_affine()

                data_src = np.array(im_src.data)
                data_dst = np.array(im_dst.data)

                for value in values:
                    pt_src = np.argwhere(data_src == value)[0]
                    pt_dst = np.argwhere(data_dst == value)[0]

                    pos_src = np.matmul(aff_src, np.hstack((pt_src, [1])).reshape((4,1)))
                    pos_dst = np.matmul(aff_dst, np.hstack((pt_dst, [1])).reshape((4,1)))
                    if 0:
                        print("P at src {}".format(pos_src.T))
                        print("P at dst {}".format(pos_dst.T))
                    assert np.allclose(pos_src, pos_dst, atol=1e-3)