示例#1
0
 def test_initialization(self):
     '''assert all parameters are correctly set up when parameters passed in'''
     my_data_2d = np.array([[1, 2, 3], [1, 2, 3]])
     o_calculate = CalculateRadialProfile(data=my_data_2d)
     assert (o_calculate.data == my_data_2d).all()
     my_data_3d = np.array([[1, 2, 3], [1, 2, 3], [0, 0, 0]])
     o_calculate = CalculateRadialProfile(data=my_data_3d)
     assert (o_calculate.data == my_data_3d).all()
     bad_dimension_data = np.array([1, 2, 3])
     self.assertRaises(ValueError, CalculateRadialProfile,
                       bad_dimension_data)
示例#2
0
    def test_report_size_of_image(self):
        '''assert the size of the array is correctly retrieved'''
        data = np.ones((20, 10))
        [height, width] = np.shape(data)
        [y0, x0] = [int(height / 2), int(width / 2)]
        center = (x0, y0)
        angle_range = (0, 90)
        o_calculate = CalculateRadialProfile(data=data)
        o_calculate.add_params(center=center, angle_range=angle_range)

        assert 10 == o_calculate.x_len
        assert 20 == o_calculate.y_len
示例#3
0
    def calculate(self, center={}, angle_range={}):

        QApplication.setOverrideCursor(QtCore.Qt.WaitCursor)

        self.center = center
        self.angle_range = angle_range

        nbr_files = len(self.working_data)

        self.parent_ui.eventProgress.setMinimum(1)
        self.parent_ui.eventProgress.setMaximum(nbr_files)
        self.parent_ui.eventProgress.setValue(1)
        self.parent_ui.eventProgress.setVisible(True)
        QtGui.QGuiApplication.processEvents()

        _array_profile = []

        self.parent_ui.ui.profile_plot.clear()
        try:
            self.parent_ui.ui.profile_plot.scene().removeItem(
                self.parent_ui.legend)
        except Exception as e:
            pass
        self.parent_ui.legend = self.parent_ui.ui.profile_plot.addLegend()
        QtGui.QGuiApplication.processEvents()

        for _index in np.arange(nbr_files):
            o_calculation = CalculateRadialProfile(
                data=self.working_data[_index],
                center=center,
                angle_range=angle_range)
            o_calculation.calculate()

            _short_file_name = self.short_list_files[_index]

            _profile = o_calculation.radial_profile
            _array_profile.append(_profile)

            self.parent_ui.eventProgress.setValue(_index + 1)

            # display
            _color = self.list_rgb_profile_color[_index]
            self.plot(_profile, _short_file_name, _color)

            QtGui.QGuiApplication.processEvents()

        QtGui.QGuiApplication.processEvents()
        self.parent_ui.eventProgress.setVisible(False)
        self.profile_data = _array_profile

        QApplication.restoreOverrideCursor()
示例#4
0
    def test_initialization_real_case(self):
        '''assert all parameters are correctly set up when real parameters are passed in'''
        assert os.path.exists(self.data_path)

        data = self.data

        [height, width] = np.shape(data)
        [y0, x0] = [int(height / 2), int(width / 2)]
        center = (x0, y0)
        angle_range = (0, 90)

        o_calculate = CalculateRadialProfile(data=data)
        o_calculate.add_params(center=center, angle_range=angle_range)
        assert (o_calculate.data == data).all()
        assert o_calculate.center == center
        assert o_calculate.angle_range == angle_range
        assert o_calculate.x0 == center[0]
        assert o_calculate.y0 == center[1]
示例#5
0
 def test_throwing_error_when_center_format_has_wrong_format(self):
     '''assert error is thrown when center does not have the right format'''
     o_calculate = CalculateRadialProfile(data=self.data)
     bad_center = (10, -1)
     self.assertRaises(ValueError, o_calculate.add_params, bad_center)
     bad_center = {10, 1}
     self.assertRaises(AssertionError, o_calculate.add_params, bad_center)
     bad_center = [10, 1]
     self.assertRaises(AssertionError, o_calculate.add_params, bad_center)
     bad_center = (10, 1, 3)
     self.assertRaises(ValueError, o_calculate.add_params, bad_center)
示例#6
0
 def test_throwing_error_when_angle_range_has_wrong_format(self):
     '''assert error is thrown when angle range does not have the right format'''
     o_calculate = CalculateRadialProfile(data=self.data)
     bad_angle_range = (-10, 40)
     self.assertRaises(ValueError, o_calculate.add_params, bad_angle_range)
     bad_angle_range = {0, 90}
     self.assertRaises(AssertionError, o_calculate.add_params,
                       bad_angle_range)
     bad_angle_range = [0, 90]
     self.assertRaises(AssertionError, o_calculate.add_params,
                       bad_angle_range)
     bad_angle_range = (90, 180, 270)
     self.assertRaises(ValueError, o_calculate.add_params, bad_angle_range)
示例#7
0
    def test_working_data_correctly_sorted(self):
        '''assert the working data are correctly sorted according to the pixel radius'''
        data = np.ones((10, 10))
        data[5][4] = 100
        [height, width] = np.shape(data)
        [y0, x0] = [int(height / 2), int(width / 2)]
        center = (x0, y0)
        angle_range = None
        o_calculate = CalculateRadialProfile(data=data)
        o_calculate.add_params(center=center, angle_range=angle_range)
        o_calculate.calculate()
        data_sorted_by_radius = o_calculate.data_sorted_by_radius

        assert ([1., 1., 100., 1.] == data_sorted_by_radius[:4]).all()
示例#8
0
    def test_sort_radius(self):
        '''assert the array of radius is correctly sorted'''
        data = np.ones((10, 10))
        [height, width] = np.shape(data)
        [y0, x0] = [int(height / 2), int(width / 2)]
        center = (x0, y0)
        angle_range = (0, 90)
        o_calculate = CalculateRadialProfile(data=data)
        o_calculate.add_params(center=center, angle_range=angle_range)
        o_calculate.calculate()
        sorted_radius = o_calculate.sorted_radius

        assert 1 == sorted_radius[0]  # pixel 0 is never used
        self.assertAlmostEqual(6.4031, sorted_radius[-1], delta=0.01)
示例#9
0
    def test_sort_indices_of_radius(self):
        '''assert the array of radius indices is correctly sorted'''
        data = np.ones((10, 10))
        [height, width] = np.shape(data)
        [y0, x0] = [int(height / 2), int(width / 2)]
        center = (x0, y0)
        angle_range = (0, 90)
        o_calculate = CalculateRadialProfile(data=data)
        o_calculate.add_params(center=center, angle_range=angle_range)
        o_calculate.calculate()
        sorted_radius_indices = o_calculate.sorted_radius_indices

        assert 55 == sorted_radius_indices[0]
        assert 0 == sorted_radius_indices[-1]
示例#10
0
    def test_calculation_of_radius_array(self):
        '''assert that the array of pixel radius is correct'''
        data = np.ones((10, 10))
        [height, width] = np.shape(data)
        [y0, x0] = [int(height / 2), int(width / 2)]
        center = (x0, y0)
        angle_range = (0, 90)
        o_calculate = CalculateRadialProfile(data=data)
        o_calculate.add_params(center=center, angle_range=angle_range)

        o_calculate.calculate()

        _radius_array = o_calculate.radius_array
        assert _radius_array[y0, x0] == 0  # center of circle
        assert _radius_array[0, 0] == pytest.approx(7.071, abs=0.01)
示例#11
0
 def test_profile(self):
     '''assert the final profile'''
     data = self.data2
     [height, width] = np.shape(data)
     [y0, x0] = [int(height / 2), int(width / 2)]
     center = (x0, y0)
     angle_range = (0, 90)
     o_calculate = CalculateRadialProfile(data=data)
     o_calculate.add_params(center=center, angle_range=angle_range)
     o_calculate.calculate()
     radial_profile = o_calculate.radial_profile
     radial_profile_array = np.array(radial_profile['mean'])
     self.assertAlmostEqual(255, radial_profile_array[0], delta=0.0001)
     self.assertAlmostEqual(255, radial_profile_array[1], delta=0.0001)
     self.assertAlmostEqual(255, radial_profile_array[2], delta=0.0001)
     self.assertAlmostEqual(255, radial_profile_array[3], delta=0.0001)
示例#12
0
 def test_new_working_data(self):
     '''assert the data outside the angle range are turned off - working data is correct'''
     data = np.ones((10, 10))
     [height, width] = np.shape(data)
     [y0, x0] = [int(height / 2), int(width / 2)]
     center = (x0, y0)
     angle_range = (0, 90)
     o_calculate = CalculateRadialProfile(data=data)
     o_calculate.add_params(center=center, angle_range=angle_range)
     o_calculate.calculate()
     working_data = o_calculate.working_data
     real_working_data = np.zeros((10, 10))
     real_working_data[:] = np.nan
     real_working_data[0:6, 5:, ] = 1
     real_working_data[y0, x0] = np.nan
     assert (working_data[0:5, 6:, ] == real_working_data[0:5, 6:, ]).all()
示例#13
0
    def test_calculate_array_of_angles(self):
        '''assert the array of angles is correct'''
        data = np.ones((10, 10))
        [height, width] = np.shape(data)
        [y0, x0] = [int(height / 2), int(width / 2)]
        center = (x0, y0)
        angle_range = (0, 90)
        o_calculate = CalculateRadialProfile(data=data)
        o_calculate.add_params(center=center, angle_range=angle_range)
        o_calculate.calculate()
        array_angle_deg = o_calculate.array_angle_deg

        assert array_angle_deg[0, 0] == 315
        assert array_angle_deg[y0, x0] == 180
        assert array_angle_deg[np.int(height / 2), 0] == 270
        self.assertAlmostEqual(array_angle_deg[height - 1, 0],
                               231.3,
                               delta=0.1)
示例#14
0
    def test_full_radial_profile(self):
        _file_path = os.path.dirname(__file__)
        data_path = os.path.abspath(
            os.path.join(_file_path, '../../notebooks/circle_profile.tif'))
        data = io.imread(data_path)
        o_calculate = CalculateRadialProfile(data=data)
        center = (500, 600)
        o_calculate.add_params(center=center)
        o_calculate.calculate()
        radial_profile = o_calculate.radial_profile

        radius_returned = radial_profile.index
        mean_counts_returned = np.array(radial_profile["mean"])

        radius_expected = [0, 1.0, 1.4142, 2.0, 2.236, 2.8284]
        for _expected, _returned in zip(radius_expected, radius_returned):
            assert _returned == pytest.approx(_expected, abs=1e-2)

        mean_counts_expected = [500.70709, 501.14412, 501.49767]
        for _expected, _returned in zip(mean_counts_expected,
                                        mean_counts_returned):
            assert _returned == pytest.approx(_expected, abs=1e-2)
示例#15
0
def simple(z,
           input_folder='stack',
           output_folder='corrected',
           angle_ini=-90,
           angle_fin=90,
           bit=32):
    '''
    Applies a beam hardening correction on a given tif sequence
    Correction is calculated on one given slide only

    --> z             = slice to use for correction, z>=1
    --> input_folder  = folder where the original tif sequence is stored
    --> output_folder = folder where the corrected tif sequence will be stored
    --> angle_ini     = initial angle for angle range for radial profile
                            angle in degrees: 0 is 12:00 and 90 is 3:00
    --> angle_fin     = final anle for angle range for radial profile (degrees)
    '''

    file_list = []
    for f in os.listdir(input_folder):
        if f.endswith('.tif'):
            file_list.append(f)
    else:
        for f in os.listdir(input_folder):
            if f.endswith('.tiff'):
                file_list.append(f)

    if not os.path.exists(output_folder):
        os.makedirs(output_folder)

    file_list.sort()
    data_file = input_folder + '/' + file_list[z - 1]
    # working_data = cv2.imread(data_file, cv2.IMREAD_GRAYSCALE)
    working_data = cv2.imread(data_file, -1)

    center = {
        'x0': working_data.shape[0] / 2 + 0.5,
        'y0': working_data.shape[1] / 2 + 0.5
    }  #pixels

    angle_range = {'from': angle_ini, 'to': angle_fin}  #degrees

    r_profile = CalculateRadialProfile(data=working_data,
                                       center=center,
                                       angle_range=angle_range)
    r_profile.calculate()
    profile = r_profile.radial_profile

    limit = int(np.where(profile == profile.max())[0])

    fig1 = plt.figure()
    plt.plot(profile)

    i = profile[:limit]
    r = np.arange(1, len(i) + 1, 1)

    # Brezier
    A = {'x': r.min(), 'y': i.min()}
    C = {'x': r.max(), 'y': i.max()}

    def funy(w, r, A, C):
        B = {'x': w[3], 'y': w[4]}
        h = ((A['x'] - B['x'] +
              np.sqrt(r * A['x'] - 2 * r * B['x'] + B['x']**2 + r * C['x'] -
                      A['x'] * C['x'])) / (A['x'] - 2 * B['x'] + C['x']))
        y = (((1 - h)**2 * A['y'] * w[0] + 2 *
              (1 - h) * h * B['y'] * w[1] + h**2 * C['y'] * w[2]) /
             ((1 - h)**2 * w[0] + 2 * (1 - h) * h * w[1] + h**2 * w[2]))
        return y

    def offset(w, A, C, r, i):
        y = funy(w, r, A, C)
        return i - y

    wopt = optimize.least_squares(
        offset, [1, 1, 1, r.max() * 2 / 3, i.min()],
        args=(A, C, r, i),
        bounds=([0, 0, 0, 0, 0], [np.inf, np.inf, np.inf, np.inf, np.inf]),
        verbose=1)

    ref = [i[int(np.max(r) / 20):int(np.max(r) / 10)].mean()] * len(i)
    corrected = i - (funy(wopt.x, r, A, C) - ref)

    fig2 = plt.figure()
    ax21 = fig2.add_subplot(121)
    ax21.plot(r, i, label='original')
    ax21.plot(r, funy(wopt.x, r, A, C), label='fitted with Bezier')
    ax21.legend()

    ax22 = fig2.add_subplot(122)
    ax22.plot(r, i, label='original')
    ax22.plot(r, corrected, label='corrected')
    ax22.plot(r, ref, label='aim')
    ax22.legend()

    fig3 = plt.figure()
    ax31 = fig3.add_subplot(121)
    ax32 = fig3.add_subplot(122)

    x_range = working_data.shape[0]
    y_range = working_data.shape[1]

    new = np.empty(working_data.shape)
    ref_z = np.full(working_data.shape, ref[0])

    @jit
    def calculate_radii(xrange, yrange, cx, cy):
        r = np.empty(working_data.shape, np.float64)
        for x in range(xrange):
            for y in range(yrange):
                r[x, y] = np.sqrt((x - cx) * (x - cx) + (y - cy) * (y - cy))
        return r

    count = 0
    radii = calculate_radii(x_range, y_range, center['x0'], center['y0'])

    for image in file_list:
        count += 1
        if count % 100 == 0:
            print('Starting slice', count, datetime.datetime.now())
        data_file_z = input_folder + '/' + image
        im_z = cv2.imread(data_file_z, -1)
        mask = radii <= limit
        foo = funy(wopt.x, radii * mask, A, C)
        new = im_z * mask - foo * mask - ref_z * mask

        os.chdir(output_folder)
        # new_n = np.float32(new)

        if bit == 32:
            new_n = np.float32(new)

        if bit == 16:
            I = cv2.normalize(new, None, 0, 65.535, cv2.NORM_MINMAX,
                              cv2.CV_16U)
            new_n = np.uint16(I)

        if bit == 8:
            I = cv2.normalize(new, None, 0, 255, cv2.NORM_MINMAX, cv2.CV_8U)
            new_n = np.uint8(I)

        cv2.imwrite(image, new_n)

        os.chdir('..')
        if count == z:
            corrected = new

    ax31.imshow(working_data)
    ax32.imshow(corrected)

    return new_n