Esempio n. 1
0
class TestDRGSDemo(VMATMixin, TestCase):
    """Tests of the result values of the DRGS demo images."""
    test_type = DRGS
    segment_positions = {0: Point(161, 192), 4: Point(314, 192)}
    segment_values = {
        0: {
            'r_dev': 0.965,
            'r_corr': 101.85
        },
        4: {
            'r_dev': -0.459,
            'r_corr': 100.42
        },
    }
    avg_abs_r_deviation = 0.46
    avg_r_deviation = 0
    max_r_deviation = 0.96
    x_offset = 20

    def setUp(self):
        self.vmat = VMAT.from_demo_images('drgs')
        self.vmat.analyze(self.test_type, x_offset=self.x_offset)

    def test_demo(self):
        """Run the demo; no errors should arise."""
        self.vmat.run_demo_drgs()
Esempio n. 2
0
    def subdivide(self, interpolation_factor=100, interpolation_type='linear'):
        """Subdivide the profile data into SingleProfiles.

        Returns
        -------
        list
            SingleProfiles
        """
        # append the peak list to include the endpoints of the profile
        peaks = self.peaks.copy()
        peaks.insert(0, Point(idx=0))
        peaks.append(Point(idx=len(self.values)))

        # create a list of single profiles from segments of original profile data.
        # New profiles are segmented by initial peak locations.
        subprofiles = []
        for idx in range(len(peaks) - 2):
            left_end = peaks[idx].idx
            peak_idx = peaks[idx + 1].idx - left_end
            right_end = peaks[idx + 2].idx

            values = self.values[int(left_end):int(right_end)]

            subprofile = SingleProfile(values, initial_peak=peak_idx)
            subprofile.interpolation_factor = interpolation_factor
            subprofile.interpolation_type = interpolation_type
            subprofiles.append(subprofile)

        return subprofiles
Esempio n. 3
0
class TestDRGS105(VMATMixin, TestCase):
    """Tests of the result values of DRMLC images at 105cm SID."""
    filepaths = ('DRGSopen-105-example.dcm', 'DRGSdmlc-105-example.dcm')
    klass = DRGS
    segment_positions = {0: Point(371, 384), 2: Point(478, 384)}
    segment_values = {
        0: {'r_dev': 1.385, 'r_corr': 15.12},
        4: {'r_dev': -0.8, 'r_corr': 14.8},
    }
    avg_abs_r_deviation = 0.68
    max_r_deviation = 1.38
Esempio n. 4
0
class TestDRGS2(VMATMixin, TestCase):
    """Tests of the result values of DRMLC images at 105cm SID."""
    filepaths = ('DRGS#2_open.dcm', 'DRGS#2_dmlc.dcm')
    klass = DRGS
    segment_positions = {0: Point(191, 192), 2: Point(242, 192)}
    segment_values = {
        0: {'r_dev': 1.5, 'r_corr': 6.4},
        4: {'r_dev': -0.7, 'r_corr': 6.3},
    }
    avg_abs_r_deviation = 0.7
    max_r_deviation = 1.5
Esempio n. 5
0
class TestDRMLC105(VMATMixin, TestCase):
    """Tests of the result values of MLCS images at 105cm SID."""
    klass = DRMLC
    filepaths = ('DRMLCopen-105-example.dcm', 'DRMLCdmlc-105-example.dcm')
    segment_positions = {0: Point(391, 384), 2: Point(552, 384)}
    segment_values = {
        0: {'r_dev': -2.1, 'r_corr': 13.6},
        2: {'r_dev': 0.22, 'r_corr': 14},
    }
    avg_abs_r_deviation = 1.06
    max_r_deviation = 2.11
    passes = False
Esempio n. 6
0
class TestDRMLC2(VMATMixin, TestCase):
    """Tests of the result values of MLCS images at 105cm SID."""
    filepaths = ('DRMLC#2_open.dcm', 'DRMLC#2_dmlc.dcm')
    klass = DRMLC
    segment_positions = {0: Point(199, 192), 2: Point(275, 192)}
    segment_values = {
        0: {'r_dev': 0.77, 'r_corr': 6.1},
        2: {'r_dev': -1.1, 'r_corr': 6},
    }
    avg_abs_r_deviation = 1.4
    max_r_deviation = 1.98
    passes = False
Esempio n. 7
0
class TestDRMLC2(VMATMixin, TestCase):
    """Tests of the result values of MLCS images at 105cm SID."""
    filepaths = (osp.join(TEST_DIR, 'DRMLC#2_open.dcm'),
                 osp.join(TEST_DIR, 'DRMLC#2_dmlc.dcm'))
    test_type = DRMLC
    segment_positions = {0: Point(199, 192), 2: Point(275, 192)}
    segment_values = {
        0: {'r_dev': 0.40, 'r_corr': 101.06},
        2: {'r_dev': -0.49, 'r_corr': 100.16},
    }
    avg_abs_r_deviation = 0.4
    avg_r_deviation = 0
    max_r_deviation = -0.49
Esempio n. 8
0
class TestDRMLC105(VMATMixin, TestCase):
    """Tests of the result values of MLCS images at 105cm SID."""
    filepaths = (osp.join(TEST_DIR, 'DRMLCopen-105-example.dcm'),
                 osp.join(TEST_DIR, 'DRMLCdmlc-105-example.dcm'))
    test_type = DRMLC
    segment_positions = {0: Point(391, 384), 2: Point(552, 384)}
    segment_values = {
        0: {'r_dev': -0.040, 'r_corr': 100.83},
        2: {'r_dev': -0.021, 'r_corr': 100.85},
    }
    avg_abs_r_deviation = 0.03
    avg_r_deviation = 0
    max_r_deviation = 0.04
Esempio n. 9
0
class TestDRGS2(VMATMixin, TestCase):
    """Tests of the result values of DRMLC images at 105cm SID."""
    filepaths = (osp.join(TEST_DIR, 'DRGS#2_open.dcm'),
                 osp.join(TEST_DIR, 'DRGS#2_dmlc.dcm'))
    test_type = DRGS
    x_offset = 12
    segment_positions = {0: Point(191, 192), 2: Point(242, 192)}
    segment_values = {
        0: {'r_dev': 1.3, 'r_corr': 103.0},
        4: {'r_dev': -0.8, 'r_corr': 100.86},
    }
    avg_abs_r_deviation = 0.7
    avg_r_deviation = 0
    max_r_deviation = 1.3
Esempio n. 10
0
class TestDRGS105(VMATMixin, TestCase):
    """Tests of the result values of DRMLC images at 105cm SID."""
    filepaths = (osp.join(TEST_DIR, 'DRGSopen-105-example.dcm'),
                 osp.join(TEST_DIR, 'DRGSdmlc-105-example.dcm'))
    test_type = DRGS
    x_offset = 20
    segment_positions = {0: Point(371, 384), 2: Point(478, 384)}
    segment_values = {
        0: {'r_dev': 0.780, 'r_corr': 102.43},
        4: {'r_dev': -0.282, 'r_corr': 101.357},
    }
    avg_abs_r_deviation = 0.34
    avg_r_deviation = 0
    max_r_deviation = 0.78
Esempio n. 11
0
class TestDRMLCWideGaps(VMATMixin, TestCase):
    """Tests of the result values of a perfect DRMLC but with very wide gaps."""
    filepaths = ('vmat-drgs-open-wide-gaps.dcm', 'vmat-drgs-open-wide-gaps.dcm')
    klass = DRMLC
    segment_positions = {0: Point(439, 640), 2: Point(707, 640)}
    segment_values = {
        0: {'r_dev': 0, 'r_corr': 100},
        2: {'r_dev': 0, 'r_corr': 100},
    }
    avg_abs_r_deviation = 0
    max_r_deviation = 0.0
    passes = True

    def test_fail_with_tight_tolerance(self):
        pass
Esempio n. 12
0
class TestDRMLCOverlapGaps(VMATMixin, TestCase):
    """Tests of the result values of a perfect DRMLC but with gaps that are overlapping (e.g. from a poor DLG)."""
    filepaths = ('vmat-drgs-open-overlap.dcm', 'vmat-drgs-open-overlap.dcm')
    klass = DRMLC
    segment_positions = {0: Point(439, 640), 2: Point(707, 640)}
    segment_values = {
        0: {'r_dev': 0, 'r_corr': 100},
        2: {'r_dev': 0, 'r_corr': 100},
    }
    avg_abs_r_deviation = 0
    max_r_deviation = 0.0
    passes = True

    def test_fail_with_tight_tolerance(self):
        pass
Esempio n. 13
0
class TestDRMLCDemo(VMATMixin, TestCase):
    """Tests of the result values of the DRMLC demo images."""
    segment_positions = {0: Point(170, 192), 2: Point(285, 192)}
    segment_values = {
        0: {'r_dev': -0.7, 'r_corr': 5.7},
        2: {'r_dev': -0.405, 'r_corr': 5.8},
    }
    avg_abs_r_deviation = 0.44
    max_r_deviation = 0.89

    def setUp(self):
        self.vmat = DRMLC.from_demo_images()
        self.vmat.analyze()

    def test_demo(self):
        self.vmat.run_demo()
Esempio n. 14
0
    def find_valleys(self,
                     threshold=0.3,
                     min_distance=0.05,
                     max_number=None,
                     search_region=(0.0, 1.0),
                     kind='index'):
        """Find the valleys (minimums) of the profile using a simple minimum value search.

        Returns
        -------
        ndarray
            Either the values or indices of the peaks.

        See Also
        --------
        :meth:`~pylinac.core.profile.MultiProfile.find_peaks` : Further parameter info.
        """
        valley_vals, valley_idxs = peak_detect(self.values,
                                               threshold,
                                               min_distance,
                                               max_number,
                                               search_region=search_region,
                                               find_min_instead=True)
        self.valleys = [
            Point(value=valley_val, idx=valley_idx)
            for valley_idx, valley_val in zip(valley_idxs, valley_vals)
        ]

        return valley_idxs if kind == INDEX else valley_vals
Esempio n. 15
0
    def _get_reasonable_start_point(self):
        """Set the algorithm starting point automatically.

        Notes
        -----
        The determination of an automatic start point is accomplished by finding the Full-Width-80%-Max.
        Finding the maximum pixel does not consistently work, esp. in the presence of a pin prick. The
        FW80M is a more consistent metric for finding a good start point.
        """
        # sum the image along each axis within the central 1/3 (avoids outlier influence from say, gantry shots)
        top_third = int(self.image.array.shape[0] / 3)
        bottom_third = int(top_third * 2)
        left_third = int(self.image.array.shape[1] / 3)
        right_third = int(left_third * 2)
        central_array = self.image.array[top_third:bottom_third,
                                         left_third:right_third]

        x_sum = np.sum(central_array, 0)
        y_sum = np.sum(central_array, 1)

        # Calculate Full-Width, 80% Maximum center
        fwxm_x_point = SingleProfile(x_sum).fwxm_center(80) + left_third
        fwxm_y_point = SingleProfile(y_sum).fwxm_center(80) + top_third
        center_point = Point(fwxm_x_point, fwxm_y_point)
        return center_point
Esempio n. 16
0
class VMATMixin:
    klass = object
    filepaths = Union[str, List]
    is_zip = False
    segment_positions = {1: Point(100, 200)}
    segment_values = {
        0: {'r_dev': 0, 'r_corr': 100},
        4: {'r_dev': 0, 'r_corr': 100},
    }
    avg_abs_r_deviation = 0
    avg_r_deviation = 0
    max_r_deviation = 0
    passes = True
    print_debug = False

    @classmethod
    def absolute_path(cls):
        if cls.is_zip:
            path = osp.join(TEST_DIR, cls.filepaths)
        else:
            path = [osp.join(TEST_DIR, path) for path in cls.filepaths]
        return path

    def setUp(self):
        if self.is_zip:
            self.vmat = self.klass.from_zip(self.absolute_path())
        else:
            self.vmat = self.klass(self.absolute_path())
        self.vmat.analyze()
        if self.print_debug:
            print(self.vmat.results())
            print(f"Segment 0: rdev {self.vmat.segments[0].r_dev:2.3f}, rcorr {self.vmat.segments[0].r_corr:2.3f}")
            if self.klass == DRGS:
                print(f"Segment 4: rdev {self.vmat.segments[4].r_dev:2.3f}, rcorr {self.vmat.segments[4].r_corr:2.3f}")
            else:
                print(f"Segment 2: rdev {self.vmat.segments[2].r_dev:2.3f}, rcorr {self.vmat.segments[2].r_corr:2.3f}")
            print("Max dev", self.vmat.max_r_deviation)

    def test_overall_passed(self):
        self.assertEqual(self.vmat.passed, self.passes)

    def test_fail_with_tight_tolerance(self):
        self.vmat.analyze(tolerance=0.01)
        self.assertFalse(self.vmat.passed)

    def test_segment_positions(self):
        for key, value in self.segment_positions.items():
            within_5(self.vmat.segments[key].center.x, value.x)
            within_5(self.vmat.segments[key].center.y, value.y)

    def test_segment_values(self):
        for key, value in self.segment_values.items():
            within_1(self.vmat.segments[key].r_dev, value['r_dev'])
            within_1(self.vmat.segments[key].r_corr, value['r_corr'])

    def test_deviations(self):
        self.assertAlmostEqual(self.vmat.avg_abs_r_deviation, self.avg_abs_r_deviation, delta=0.05)
        self.assertAlmostEqual(self.vmat.avg_r_deviation, self.avg_r_deviation, delta=0.02)
        self.assertAlmostEqual(self.vmat.max_r_deviation, self.max_r_deviation, delta=0.1)
Esempio n. 17
0
class VMATMixin:
    filepaths = ('open', 'dmlc')
    is_zip = False
    test_type = ''
    x_offset = 0
    segment_positions = {1: Point(100, 200)}
    segment_values = {
        0: {
            'r_dev': 0,
            'r_corr': 100
        },
        4: {
            'r_dev': 0,
            'r_corr': 100
        },
    }
    avg_abs_r_deviation = 0
    avg_r_deviation = 0
    max_r_deviation = 0
    passes = True

    def setUp(self):
        if self.is_zip:
            self.vmat = VMAT.from_zip(self.filepaths)
        else:
            self.vmat = VMAT(self.filepaths)
        self.vmat.analyze(self.test_type, x_offset=self.x_offset)

    def test_overall_passed(self):
        self.vmat.analyze(self.test_type, x_offset=self.x_offset)
        self.assertEqual(self.vmat.passed, self.passes)

    def test_fail_with_tight_tolerance(self):
        self.vmat.analyze(self.test_type,
                          tolerance=0.01,
                          x_offset=self.x_offset)
        self.assertFalse(self.vmat.passed)

    def test_segment_positions(self):
        for key, value in self.segment_positions.items():
            within_1(self.vmat.segments[key].center.x, value.x)
            within_1(self.vmat.segments[key].center.y, value.y)

    def test_segment_values(self):
        for key, value in self.segment_values.items():
            within_01(self.vmat.segments[key].r_dev, value['r_dev'])
            within_01(self.vmat.segments[key].r_corr, value['r_corr'])

    def test_deviations(self):
        self.assertAlmostEqual(self.vmat.avg_abs_r_deviation,
                               self.avg_abs_r_deviation,
                               delta=0.05)
        self.assertAlmostEqual(self.vmat.avg_r_deviation,
                               self.avg_r_deviation,
                               delta=0.02)
        self.assertAlmostEqual(self.vmat.max_r_deviation,
                               self.max_r_deviation,
                               delta=0.1)
Esempio n. 18
0
 def mm2dots(self, point):
     """Wandelt Point Angaben von mm nach dot.
     
     Parameters
     ----------
     point : Point
     
     """
     return Point(self.mm2dots_X(point.x), self.mm2dots_Y(point.y))
Esempio n. 19
0
 def dots2mm(self, point):
     """Wandelt Point Angaben von dot nach mm
     
     Parameters
     ----------
     point : Point
     
     """
     return Point(self.dots2mm_X(point.x), self.dots2mm_Y(point.y))
Esempio n. 20
0
class TestDRGSDemo(VMATMixin, TestCase):
    """Tests of the result values of the DRGS demo images."""
    segment_positions = {0: Point(161, 192), 4: Point(314, 192)}
    segment_values = {
        0: {'r_dev': 0.965, 'r_corr': 6.2},
        4: {'r_dev': -0.459, 'r_corr': 6},
    }
    avg_abs_r_deviation = 0.66
    max_r_deviation = 1.8
    passes = False

    def setUp(self):
        self.vmat = DRGS.from_demo_images()
        self.vmat.analyze()

    def test_demo(self):
        """Run the demo; no errors should arise."""
        self.vmat.run_demo()
Esempio n. 21
0
class Demo(StarMixin, TestCase):
    """Specific tests for the demo image"""
    wobble_diameter_mm = 0.30
    wobble_center = Point(1270, 1437)
    num_rad_lines = 4

    @classmethod
    def construct_star(cls):
        return Starshot.from_demo_image()
Esempio n. 22
0
class TestDRMLCDemo(VMATMixin, TestCase):
    """Tests of the result values of the DRMLC demo images."""
    test_type = DRMLC
    segment_positions = {0: Point(170, 192), 2: Point(285, 192)}
    segment_values = {
        0: {'r_dev': 0.437, 'r_corr': 100.89},
        2: {'r_dev': -0.405, 'r_corr': 100.04},
    }
    avg_abs_r_deviation = 0.38
    avg_r_deviation = 0
    max_r_deviation = 0.44

    def setUp(self):
        self.vmat = VMAT.from_demo_images('drmlc')
        self.vmat.analyze(self.test_type, x_offset=self.x_offset)

    def test_demo(self):
        self.vmat.run_demo_drmlc()
Esempio n. 23
0
    def _flip_image_data(self) -> None:
        """Flip the image left->right and invert the center, and angle as appropriate.

        Sometimes the Leeds phantom is set upside down on the imaging panel. Pylinac's
        analysis goes counter-clockwise, so this method flips the image and coordinates to
        make the image ccw. Quicker than flipping the image and reanalyzing.
        """
        self.image.array = np.fliplr(self.image.array)
        new_x = self.image.shape[1] - self.phantom_center.x
        self._phantom_center = Point(new_x, self.phantom_center.y)
Esempio n. 24
0
 def test_phan_center(self):
     """Test locations of the phantom center."""
     known_phan_center = Point(257, 255)
     self.cbct.analyze()
     self.assertAlmostEqual(self.cbct.ctp404.phan_center.x,
                            known_phan_center.x,
                            delta=0.7)
     self.assertAlmostEqual(self.cbct.ctp404.phan_center.y,
                            known_phan_center.y,
                            delta=0.7)
Esempio n. 25
0
    def _find_bb(self):
        """Find the BB within the radiation field. Iteratively searches for a circle-like object
        by lowering a low-pass threshold value until found.

        Returns
        -------
        Point
            The weighted-pixel value location of the BB.
        """

        def is_boxlike(array):
            """Whether the binary object's dimensions are symmetric, i.e. box-like"""
            ymin, ymax, xmin, xmax = get_bounding_box(array)
            y = abs(ymax - ymin)
            x = abs(xmax - xmin)
            if x > max(y * 1.05, y+3) or x < min(y * 0.95, y-3):
                return False
            return True

        # get initial starting conditions
        hmin = np.percentile(self.array, 5)
        hmax = self.array.max()
        spread = hmax - hmin
        max_thresh = hmax

        # search for the BB by iteratively lowering the low-pass threshold value until the BB is found.
        found = False
        while not found:
            try:
                lower_thresh = hmax - spread / 2
                t = np.where((max_thresh > self) & (self >= lower_thresh), 1, 0)
                labeled_arr, num_roi = ndimage.measurements.label(t)
                roi_sizes, bin_edges = np.histogram(labeled_arr, bins=num_roi + 1)
                bw_node_cleaned = np.where(labeled_arr == np.argsort(roi_sizes)[-3], 1, 0)
                expected_fill_ratio = np.pi / 4
                actual_fill_ratio = get_filled_area_ratio(bw_node_cleaned)
                if (expected_fill_ratio * 1.1 < actual_fill_ratio) or (actual_fill_ratio < expected_fill_ratio * 0.9):
                    raise ValueError
                if not is_boxlike(bw_node_cleaned):
                    raise ValueError
            except (IndexError, ValueError):
                max_thresh -= 0.05 * spread
                if max_thresh < hmin:
                    raise ValueError("Unable to locate the BB")
            else:
                found = True

        # determine the center of mass of the BB
        inv_img = Image.load(self.array)
        inv_img.invert()
        x_arr = np.abs(np.average(bw_node_cleaned, weights=inv_img, axis=0))
        x_com = SingleProfile(x_arr).fwxm_center(interpolate=True)
        y_arr = np.abs(np.average(bw_node_cleaned, weights=inv_img, axis=1))
        y_com = SingleProfile(y_arr).fwxm_center(interpolate=True)
        return Point(x_com, y_com)
Esempio n. 26
0
class Demo(StarMixin, TestCase):
    """Specific tests_basic for the demo image"""
    wobble_diameter_mm = 0.30
    wobble_center = Point(1270, 1437)
    num_rad_lines = 4
    wobble_tolerance = 0.15
    # independently verified: 0.24-0.26mm

    @classmethod
    def construct_star(cls):
        return Starshot.from_demo_image()
Esempio n. 27
0
 def cax(self):
     """The position of the beam central axis. If no DICOM translation tags are found then the center is returned."""
     try:
         x = self.center.x - self.dicom_dataset.XRayImageReceptorTranslation[
             0]
         y = self.center.y - self.dicom_dataset.XRayImageReceptorTranslation[
             1]
     except AttributeError:
         return self.center
     else:
         return Point(x, y)
Esempio n. 28
0
    def test_phan_center(self):
        """Test locations of the phantom center."""
        self.cbct.load_demo_images()

        known_phan_center = Point(257, 255)
        self.cbct.analyze()
        self.assertAlmostEqual(self.cbct.hu.phan_center.x,
                               known_phan_center.x,
                               delta=0.7)
        self.assertAlmostEqual(self.cbct.hu.phan_center.y,
                               known_phan_center.y,
                               delta=0.7)
Esempio n. 29
0
    def _findArrayIsoCalCenter(self, imageArray, debug=False):
        """ Zentrum des ISO Cal (Einschub) Phantom im array bestimmen 
        
        Parameters
        ----------
        imageArray : array
            array der Bilddaten
        debug : boolean
            debug Bilder augeben
            
        Returns
        -------
        Point
            gefundenes Zentrum in pixel
        """
        # imageArray invertieren
        img_inv = -imageArray + imageArray.max() + imageArray.min()

        # eine Bildmaske des großen kreises erstellen
        labeled_foreground = (img_inv >
                              filters.threshold_otsu(img_inv)).astype(int)
        # eine Auswertung der Bildmaske vornehmen
        properties = measure.regionprops(labeled_foreground)
        # es könnten mehrere objekte vorhanden sein
        # in unseren Bildern ist aber nur eins deshalb das erste verwenden

        # das gefundene Zentrum des ISO Cal Phantomstiftes in dots
        isoCalDot = Point(properties[0].centroid[1], properties[0].centroid[0])

        if self.debug:
            # plot images zum debuggen
            plots = {'Original': imageArray, 'Labels': labeled_foreground}
            fig, ax = plt.subplots(1, len(plots))
            for n, (title, img) in enumerate(plots.items()):
                cmap = plt.cm.gnuplot if n == len(plots) - 1 else plt.cm.gray
                ax[n].imshow(img, cmap=cmap)
                ax[n].axis('off')
                ax[n].set_title(title)
                ax[n].plot(isoCalDot.x,
                           isoCalDot.y,
                           'r+',
                           ms=80,
                           markeredgewidth=1)
                ax[n].plot(len(img) / 2,
                           len(img) / 2,
                           'y+',
                           ms=100,
                           markeredgewidth=1)
            plt.show(fig)
            #print("isoCalCenter", isoCalDot )

        return isoCalDot
Esempio n. 30
0
class StarMixin:
    """Mixin for testing a starshot image."""
    star_file = ''
    wobble_diameter_mm = 0
    wobble_center = Point()
    num_rad_lines = 0
    recursive = True
    passes = True
    min_peak_height = 0.25
    test_all_radii = True
    fwxm = True
    wobble_tolerance = 0.2

    @classmethod
    def setUpClass(cls):
        cls.star = Starshot(cls.star_file)
        cls.star.analyze(recursive=cls.recursive, min_peak_height=cls.min_peak_height, fwhm=cls.fwxm)

    @classmethod
    def tearDownClass(cls):
        plt.close('all')

    def test_passed(self):
        """Test that the demo image passed"""
        self.star.analyze(recursive=self.recursive, min_peak_height=self.min_peak_height)
        self.assertEqual(self.star.passed, self.passes, msg="Wobble was not within tolerance")

    def test_wobble_diameter(self):
        """Test than the wobble radius is similar to what it has been shown to be)."""
        self.assertAlmostEqual(self.star.wobble.diameter_mm, self.wobble_diameter_mm, delta=self.wobble_tolerance)

    def test_wobble_center(self):
        """Test that the center of the wobble circle is close to what it's shown to be."""
        # test y-coordinate
        y_coord = self.star.wobble.center.y
        self.assertAlmostEqual(y_coord, self.wobble_center.y, delta=3)
        # test x-coordinate
        x_coord = self.star.wobble.center.x
        self.assertAlmostEqual(x_coord, self.wobble_center.x, delta=3)

    def test_num_rad_lines(self):
        """Test than the number of radiation lines found is what is expected."""
        self.assertEqual(len(self.star.lines), self.num_rad_lines,
                         msg="The number of radiation lines found was not the number expected")

    def test_all_radii_give_same_wobble(self):
        """Test that the wobble stays roughly the same for all radii."""
        if self.test_all_radii:
            star = Starshot(self.star_file)
            for radius in np.linspace(0.9, 0.25, 8):
                star.analyze(radius=float(radius), min_peak_height=self.min_peak_height, recursive=self.recursive)
                self.assertAlmostEqual(star.wobble.diameter_mm, self.wobble_diameter_mm, delta=self.wobble_tolerance)
Esempio n. 31
0
    def cax_line_projection(self):
        """The projection of the field CAX through space around the area of the BB.
        Used for determining gantry isocenter size.

        Returns
        -------
        Line
            The virtual line in space made by the beam CAX.
        """
        p1 = Point()
        p2 = Point()
        UPPER_QUADRANT = self.gantry_angle <= 45 or self.gantry_angle >= 315 or 225 >= self.gantry_angle > 135
        LR_QUADRANT = 45 < self.gantry_angle <= 135 or 225 < self.gantry_angle < 315
        if UPPER_QUADRANT:
            p1.y = 2
            p2.y = -2
            p1.z = self.z_offset
            p2.z = self.z_offset
            p1.x = 2 * tan(self.gantry_angle) + self.x_offset * cos(self.gantry_angle)
            p2.x = - 2 * tan(self.gantry_angle) + self.x_offset * cos(self.gantry_angle)
        elif LR_QUADRANT:
            p1.x = 2
            p2.x = -2
            p1.z = self.z_offset
            p2.z = self.z_offset
            p1.y = 2 / tan(self.gantry_angle) + self.y_offset * cos(self.gantry_angle - 90)
            p2.y = - 2 / tan(self.gantry_angle) + self.y_offset * cos(self.gantry_angle - 90)
        l = Line(p1, p2)
        return l